A guess that the Swift type alias mechanism is the automatic initializer Inheritance - swift

The question popped in my head, what is happening when I define a Swift type alias? What is the mechanism behind it? Until I learned the Automatic Initializer Inheritance chapter from the Swift official document:
If your subclass doesn't define any designated initializer, it automatically inherits all of its superclass designated initializers
And here is my practice code for learning
class Vehicle{
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
class Auto: Vehicle{}
let VM = Auto()
VM.numberOfWheels
Wow! this works,at least performs, exactly as the Swift type alias. Auto is the alias of the type Vehicle
Question: Am I understand it right? This is the mechanism behind type alias.

Question: Am I understand it right? This is the mechanism behind type alias.
NO, typealises and subclassing (with inheriting all methods and initializers) are different things and based on different semantics and mechanisms.
let v1 = Vehicle()
v1 is Auto //->false
typealias Norimono = Vehicle
v1 is Norimono //->true (with warning "'is' test is always true)
The last result (including the warning you may find) is exactly the same as v1 is Vehicle.
Typealias is literally an alias, it's giving another name for the same type.
One more, you can define typealias of structs or enums, which you cannot define inherited classes (types).

Not really, but if you've never seen object oriented programming they could look somewhat similar, i agree.
Auto is a subclass that extends the original vehicle and could add additional properties and method to the Vehicle even if in that example it doesn't do it.
Auto and Vehicle are not the same thing, a Vehicle is a basic type and and Auto is one of its subtypes, what you can do with a Vehicle you can do with an Auto but not vice-versa.
A typealias is just an alias, a way to give and additional "name" to a pre-existing type, just that. A type and his alias are the same thing.

Related

How to make TypeAliases Hashable

I have the following definitions and a type alias:
`typealias Alien = AlienClass & AlienProtocol`
`class AlienClass: SKSpriteNode {}`
`protocol AlienProtocol {}`
In order to store an object in a Set (or Map) it needs to be Hashable. SKSpriteNode is hashable, so I have no problem with let s = Set<AlienClass>().
However, if I use let s = Set<AlienClass>() then I get the error Protocol 'Alien' (aka 'AlienClass & AlienProtocol') as a type cannot conform to 'Hashable'.
Is there any way to force the typealias to inherit the hash function from its underlying AlienClass (which itself inherits from SKSpriteNode)?
I ran into this same issue when trying to store protocols in Sets directly. I stumbled upon Type Erasure but this doesn’t seem to work for heterogenous objects in the set. My hacky workaround has been to store the objects implementing the interface in a map like so: var AlienProtocols: [SKSpriteNode: AlienProtocol] = [:]. This really isn't great though, so a better pattern would be helpful.

Swift: Protocol With associatedType

I have a question about Protocol with associated type, why I can not make the protocol a type of my instance for example:
I know I can use Type Erasure to fix the issue, but why protocol with an associated type does not like to be a type of an instance, and if you will say because the associated type is also used as a constraint, well I want to implement the properties inside the protocol not inside its extensions since protocol extensions has the power to control who can access its properties, why we still have this issue.
Thank you.
There are lots of articles and answers (like this one) out there describing why but in summary, It needs associatedtype. Variables can not have an associatedtype. So alongside with Type Erasure method (that you don't want), you can simply make it opaque with adding some keyword to the type:
var objectA: some ProtocolA = A()

In swift, why can't I instantiate a protocol when it has an initialiser?

I understand that generally I cannot instantiate a protocol.
But if I include an initialiser in the protocol then surely the compiler knows that when the protocol is used by a struct or class later, it will have an init which it can use?
My code is as below and line:
protocol Solution {
var answer: String { get }
}
protocol Problem {
var pose: String { get }
}
protocol SolvableProblem: Problem {
func solve() -> Solution?
}
protocol ProblemGenerator {
func next() -> SolvableProblem
}
protocol Puzzle {
var problem: Problem { get }
var solution: Solution { get }
init(problem: Problem, solution: Solution)
}
protocol PuzzleGenerator {
func next() -> Puzzle
}
protocol FindBySolvePuzzleGenerator: PuzzleGenerator {
var problemGenerator: ProblemGenerator { get }
}
extension FindBySolvePuzzleGenerator {
func next() -> Puzzle {
while true {
let problem = problemGenerator.next()
if let solution = problem.solve() {
return Puzzle(problem: problem, solution: solution)
}
}
}
}
The line:
return Puzzle(problem: problem, solution: solution)
gives error: Protocol type 'Puzzle' cannot be instantiated
Imagine protocols are adjectives. Movable says you can move it, Red says it has color = "red"... but they don't say what it is. You need a noun. A Red, Movable Car. You can instantiate a Car, even when low on details. You cannot instantiate a Red.
But if I include an initialiser in the protocol then surely the compiler knows that when the protocol is used by a struct or class later, it will have an init which it can use?
Protocols must be adopted by classes, and there might be a dozen different classes that all adopt your Puzzle protocol. The compiler has no idea which of those classes to instantiate.
Protocols give us the power to compose interfaces without the complexity of multiple inheritance. In a multiple inheritance language like C++, you have to deal with the fact that a single class D might inherit from two other classes, B and C, and those two classes might happen to have methods or instance variables with the same name. If they both have a methodA(), and B::methodA() and C::methodA() are different, which one do you use when someone call's D's inherited methodA()? Worse, what if B and C are both derived from a common base class A? Protocols avoid a lot of that by not being directly instantiable, while still providing the interface polymorphism that makes multiple inheritance attractive.
I understand that I can't do it - I just want to understand why the
compiler can't do it?
Because protocols in Swift represent abstraction mechanism. When it comes to abstraction, you could think about it as a template, we don't have to care about the details of how it behaves or what's its properties; Thus it makes no sense to be able to create an object from it.
As a real world example, consider that I just said "Table" (as an abstracted level), I would be pretty sure that you would understand what I am talking about! nevertheless we are not mentioning details about it (such as its material or how many legs it has...); At some point if I said "create a table for me" (instantiate an object) you have the ask me about specs! and that's why the complier won't let you create object directly from a protocol. That's the point of making things to be abstracted.
Also, checking: Why can't an object of abstract class be created? might be helpful.
Unfortunately swift does not allow that even with such "hack"
You would need to use a class that confirms to that protocol as an object you refer to.
When you instantiate an object, the Operating System has to know how to allocate and deal with that kind of object in the memory: Is it a reference type (Classes)? Strong, weak or unowned reference? Or is it a value type (Structs, Strings, Int, etc)?
Reference types are stored in the Heap, while value types live in the Stack. Here is a thorough explanation of the difference between the two.
Only Reference and Value types (objects) can be instantiated. So, only the objects that conform to that protocol can then be instantiated, not the protocol itself. A protocol is not an object, it is a general description or schema of a certain behavior of objects.
As to Initialization, here what the Apple docs say:
Initialization is the process of preparing an instance of a class,
structure, or enumeration for use. This process involves setting an
initial value for each stored property on that instance and performing
any other setup or initialization that is required before the new
instance is ready for use.

Implement ExpressibleByStringLiteral on abstract base class

I have a pretty simple class structure where an "abstract" base class, Node, is implemented in a few concrete subclasses. In my case the base class represents the common interface to the object and therefore most type references are purely Node for simplicity.
However what I want to do now is implement support for ExpressibleByStringLiteral on the abstract Node such that I can instantiate a specific (of my choosing) concrete subclass when a String is interpreted as a Node.
The problem is ExpressibleByStringLiteral doesn't seem to want to allow me to do this because it requires I implement a required initializer as opposed to a static function (which would make way more sense, imo). I've gotten it able to work on one of the concrete subclasses, but that's pretty useless to me given that the concrete type is rarely used explicitly (and in fact I'd prefer it not be), as everything goes through the base Node type.
What I want is to be able to do this:
let node: Node = "textual representation of a node"
Since the subclasses are still Nodes, this doesn't violate any object oriented principles, yet Swift doesn't seem to want to let me do it.
Is there any way around this, or is this just a limitation of ExpressibleByStringLiteral?

Metatype of Metatype

In Swift we are able to write following construction:
class SomeClass {}
let metaMetatype: SomeClass.Type.Type = SomeClass.Type.self
Here metaMetatype does not conform to type AnyObject (SomeClass.Type does). Construction can be even longer, as long as we wish:
let uberMetatype: SomeClass.Type.Type.Type.Type.Type.Type.Type.Type.Type.Type = SomeClass.Type.Type.Type.Type.Type.Type.Type.Type.Type.self
Are this constructions have any sense? If SomeClass.Type.Type not an object, what is this, and why we able to declare it?
If SomeClass.Type.Type not an object, what is this and why we able to declare it?
I will try to dissect what you're asking.
SomeClass.Type.Type is a Metatype of a Metatype. Metatypes exist in Swift because Swift has types that are not classes. This is most similar to the Metaclass concept in Objective-C.
Lexicon.rst in the Swift Open Source Repo has a pretty good explanation:
metatype
The type of a value representing a type. Greg Parker has a good
explanation of Objective-C's "metaclasses" because Swift has types
that are not classes, a more general term is used.
We also sometimes refer to a value representing a type as a "metatype
object" or just "metatype", usually within low-level contexts like IRGen
and LLDB. This is technically incorrect (it's just a "type object"), but
the malapropism happened early in the project and has stuck around.
Why are we able to declare a type of a type of a type... and so on? Because it's a feature of the language called type metadata:
type metadata
The runtime representation of a type, and everything you can do with it.
Like a Class in Objective-C, but for any type.
Note that you can't do something like NSObject().class in Swift because class is a reserved keyword for the creation of a class. This is how you would get the type (or class in this case) of an NSObject in Swift:
let nsObj = NSObject()
nsObj.classForCoder // NSObject.Type
nsObj.classForKeyedArchiver // NSObject.Type
nsObj.dynamicType // NSObject.Type
Note that nsObj and nsObj.self are identical and represent the instance of that NSObject.
I don't see where in the Swift module or open source repo where types allow for .Type, but I'm still looking. It might have to do with the inheritance from SwiftObject, the Objective-C object all Swift classes inherit from (at least on Mac).
Type of a class is also represented in memory (it has for example their own methods). It's represented by singleton representing the Type. (It's not an instance of this type - that's something different). If you call self on a Type like this SomeClass.self you will take singleton instance representing the SomeClass Type.
For more info check this answer