I am trying to understand : "self, dynamicType, Type
". I have this code :
class SomeClass {}
let cls : SomeClass.Type = SomeClass.self
let cls2 : SomeClass = SomeClass()
Are cls
and cls2
the same thing ?
Can someone give some detail about the differences ? Thanks
No, cls
and cls2
are different things. The easiest way to understand the difference will be to extend your example like this:
class SomeClass {
class func doIt() {
print("I'm a class method. I belong to my type.")
}
func doItOnlyIfInstanceOfThisType() {
print("I'm a instance method. I belong to my type instance.")
}
}
And now let's take your cls
:
let cls : SomeClass.Type = SomeClass.self
cls.doIt()
That will print I'm a class method. I belong to my type.
. But you cannot invoke this:
cls.doItOnlyIfInstanceOfThisType() // causes a compilation error, PRO TIP: actually you can use this method as a func property, but I'll add the explanation for this later
Let's take your cls2
. The only visible method of it is doItOnlyIfInstanceOfThisType
because it's an instance method (of this type).
let cls2 : SomeClass = SomeClass()
cls2.doItOnlyIfInstanceOfThisType()
So the difference between them is that cls
is a type and cls2
is an instance of this type.
A little bit more knowledge about why SomeClass.self and SomeClass()?
The type of a class also exists in memory (it has for example its own methods), as a singleton representing the Type (not an instance of this type - that's something different).
If you call self
on a Type like this SomeClass.self
you will get a singleton instance representing the SomeClass
Type.
SomeClass()
invokes the init()
method of SomeClass
, a constructor that creates an instance of SomeClass
.
PRO Tip
You can manipulate a Type instance function (like closures/blocks in ObjC). It's a generated class method. But you must pass an instance of the type that you take this method from as an argument, like this:
let myFunc :()->() = cls.doItOnlyIfInstanceOfThisType(cls2)
myFunc()
A metatype type refers to the type of any type, including class types, structure types, enumeration types, and protocol types.
You can use the postfix self expression to access a type as a value. For example, SomeClass.self
returns SomeClass
itself, not an instance of SomeClass
. And SomeProtocol.self
returns SomeProtocol
itself, not an instance of a type that conforms to SomeProtocol
at runtime. You can use a dynamicType
expression with an instance of a type to access that instance’s dynamic, runtime type as a value, as the following example shows:
class SomeBaseClass {
class func printClassName() {
print("SomeBaseClass")
}
}
class SomeSubClass: SomeBaseClass {
override class func printClassName() {
print("SomeSubClass")
}
}
let someInstance: SomeBaseClass = SomeSubClass()
someInstance.dynamicType.printClassName()
// prints "SomeSubClass"
The compile-time type of someInstance
is SomeBaseClass
,
the runtime type of someInstance
is SomeSubClass
You can use the identity operators (=== and !==) to test whether an instance’s runtime type is the same as its compile-time type.
if someInstance.dynamicType === SomeBaseClass.self {
print("The dynamic type of someInstance is SomeBaseCass")
} else {
print("The dynamic type of someInstance isn't SomeBaseClass")
}
More detail -> The Swift Programming Language: Types
.dynamicType
is deprecated, you should use type(of:)
to get its meta type:
type(of: someInstance).printClassName()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With