D
D
doublench212017-10-08 23:12:52
iOS
doublench21, 2017-10-08 23:12:52

What do A.Type and A.self, where A is a class, mean in Swift?

What do A.Type and A.self mean, where A is some class, in Swift language?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Zhilin, 2017-10-10
@doublench21

For any type T, T.Typeis a metatype, that is, a type whose objects provide a description of the type T. Static functions and init-functions Tbecome member functions T.Type. Example:

struct Duck {
    static func kind() -> String { return "Bird" }
    init() { }
    func talk() { print("Quack") }
}

let meta: Duck.Type = Duck.self
meta.kind()  //=> Bird
let obj: Duck = meta.init()
obj.talk()  //=> Quack

There are 2 classes of metatypes, but in practice there are existential metatypes, that is, their objects can describe both the given type Tand any successor (subtype) of the type T. In other words, the set of type objects T.Typeis U.selffor all types U: T. Example:
class Animal { class var name: String { return "Animal" } }
class Cat: Animal { override class var name: String { return "Cat" } }
class Dog: Animal { override class var name: String { return "Dog" } }

var meta: Animal.Type
meta = Cat.self
meta.name  //=> Cat
meta = Dog.self
meta.name  //=> Dog

Or, for example, you can imagine the following animal generation function:
class Animal { ... }

func createAnimal(_ type: Animal.Type) -> Animal {
    if type == Cat.self {
        return Cat(...)
    } else if type == Dog.self {
        return Dog(...)
    } else {
        fatalError()
    }
}

In practice, this metatype functionality is rarely used. As a rule, they serve for explicit specialization of template functions. For example:
Here, the only way to specify the type U when calling is to pass a "dummy" type parameter U.Type, since the Ufunction does not accept type arguments. Rather, this is the best and accepted way in Swift. It would be possible to get out like this:
But, it is clear that for this you need to have an object of type U at hand, and this is not an ideal option. It is a pity that it is impossible to write simply unsafeCast<U>(t)at a call.
When using a metatype U.Typein this way, its value is generally ignored. That is, even if you pass the metatype of the heir of type U there, the function will still work with U.
PS There are many more undocumented features of metatypes in Swift, but everything is not very logical and thoughtful there (even the developers from the Core team do not understand everything there), so in practice it is better to limit yourself to using explicit specialization of functions, as shown above.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question