Metatype
// 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)
👉 Vector2D
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 ⭐️
Last updated
Was this helpful?