// metatype of a (class, struct, enum) type
SomeType.Type
// metatype of a protocol
SomeProtocol.Type
A metatype type refers to the type of any type, including class types, structure types, enumeration types, and protocol types.
The dynamic type (runtime type) returned from type(of:) is a concrete metatype (T.Type) for a class, struct, enum, or other nonprotocol type T, or an existential metatype (P.Type) for a protocol or protocol compositionP. ๐1๏ธ2๏ธ
When the static type (compile-time type) of the value passed to type(of:) is constrained to a class or protocol, you can use that metatype to access initializers or other static members of the class or protocol. ๐1๏ธ3๏ธ
Use an initializer expression to construct an instance of a type from that typeโs metatype value. ๐3๏ธ4๏ธ
For class instances, the initializer thatโs called must be marked with required or the entire class marked with final. ๐4๏ธ
(the compiler must make sure the initializer is implemented by every possible subtype of the type)
// base class
class A {
class var className: String { "A" } // โญ๏ธ static member
}
// subclass
class B: A {
override class var className: String { "B" }
}
let obj: A = B() // โญ๏ธ compile-time type: A
// โญโโโโโโโโโโโโฎ โ โญ๏ธ runtime type as a value
type(of: obj).className // โญ๏ธ runtime type: B
// parameter `value`
func printInfo(_ value: Any) { // โญ๏ธ static : Any
let t = type(of: value) // โญ๏ธ dynamic: Int
print("'\(value)' of type '\(t)'")
}
// constant `count`
let count: Int = 5 // static: Int, dynamic: Int (same)
printInfo(count)
extension Vector2D {
/// convert one conforming type to another type
/// with the **same vector field**.
///
/// Example:
/// ```
/// let u = CGPoint(x: 1, y: 2)
/// u.as(CGSize.self) // โญ๏ธ `CGSize.self`: access type as a value
/// ```
// โญ๏ธ โญโ1โโฎ โญโ2โโโฎ
public func `as`<T:Vector2D>(_ typeT: T.Type) -> T
where T.Field == Self.Field
{
// โญโโโโโโโโ 3 โโโโโโโโโโฎ
return typeT.init(x: x, y: y)
}
}
// โญ๏ธ 1. parameter (type T as a value)
// โญ๏ธ 2. metatype of type T
// โญ๏ธ 3. initializer expresssion
// subclass of A
class C: A {
let name: String
required init(name: String) { // โญ๏ธ marked with `required`
self.name = name
}
override class var className: String { "C" }
}
// โญโ1โโโฎ โญโ2โโโฎ
let typeC: C.Type = C.self
// โญ๏ธ 1. metatype of type `C`
// โญ๏ธ 2. access type `C` as a value
// โญ๏ธ initializing from a metatype value must reference 'init' explicitly
// โญโโโโโโโโ 3 โโโโโโโโโโฎ
let obj = typeC.init(name: "hi") // type C's instance
// โญ๏ธ 3. initializer expresssion
iOS 15 Programming Fundamentals with Swift (2021) - Type Reference, p.187 โญ๏ธ