> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/ios/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/ios/swift/debugging/metatype.md).

# Metatype

```swift
// metatype of a (class, struct, enum) type
SomeType.Type

// metatype of a protocol
SomeProtocol.Type
```

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="info" %}
A *<mark style="color:red;">**metatype type**</mark>* refers to the <mark style="color:red;">**type of any type**</mark>, including **class** types, **structure** types, **enumeration** types, and **protocol** types.
{% endhint %}

{% hint style="info" %}

* The <mark style="color:red;">**dynamic type**</mark> (runtime type) returned from <mark style="color:purple;">**type(of:)**</mark> is a *<mark style="color:red;">**concrete metatype**</mark>* (<mark style="color:purple;">**T.Type**</mark>) for a **class**, **struct**, **enum**, or other **nonprotocol** type `T`, or an *<mark style="color:red;">**existential metatype**</mark>* (<mark style="color:purple;">**P.Type**</mark>) for a <mark style="color:red;">**protocol**</mark> or <mark style="color:red;">**protocol composition**</mark> `P`.  :point\_right: :digit\_one::digit\_two:
* When the <mark style="color:red;">**static type**</mark> (compile-time type) of the <mark style="color:red;">**value**</mark> passed to <mark style="color:purple;">**type(of:)**</mark> is <mark style="color:red;">**constrained**</mark> to a <mark style="color:red;">**class**</mark> or <mark style="color:red;">**protocol**</mark>, you can use that <mark style="color:red;">**metatype**</mark> to access <mark style="color:red;">**initializers**</mark> or other <mark style="color:red;">**static members**</mark> of the **class** or **protocol**. :point\_right: :digit\_one::digit\_three:
  {% endhint %}

{% hint style="info" %}

* Use an <mark style="color:red;">**initializer expression**</mark> to construct an **instance** of a type from that <mark style="color:red;">**type’s metatype value**</mark>.  :point\_right: :digit\_three::digit\_four:
* For <mark style="color:red;">**class instances**</mark>, the <mark style="color:purple;">**initializer**</mark> that’s called must be **marked** with <mark style="color:purple;">**required**</mark> or the <mark style="color:red;">**entire class**</mark> marked with <mark style="color:red;">**final**</mark>. :point\_right::digit\_four:\
  (the compiler must make sure the **initializer** is **implemented** by **every possible subtype** of the type)
  {% endhint %}
  {% endtab %}

{% tab title="1" %}

```swift
// 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
```

{% endtab %}

{% tab title="2" %}

```swift
                                    // 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)
```

{% endtab %}

{% tab title="3" %}
:point\_right: [Vector2D](/ios/custom/package/geometrykit/vector2d.md)

````swift
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
````

{% endtab %}

{% tab title="4" %}

```swift
// 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
```

{% endtab %}

{% tab title="📘 手冊" %}

* [x] Swift Reference ⟩ [Metatype Type](https://docs.swift.org/swift-book/ReferenceManual/Types.html#ID455)
* [x] SwiftRocks ⟩ [What's .self, .Type and .Protocol? Understanding Swift Metatypes](https://swiftrocks.com/whats-type-and-self-swift-metatypes.html) ⭐️
* [ ] Swift ⟩ [Debugging and Reflection](https://developer.apple.com/documentation/swift/swift_standard_library/debugging_and_reflection) ⟩ [type(of:)](https://developer.apple.com/documentation/swift/2885064-type) - dynamic (**runtime**) type of a value
  * [ ] [Dynamic Type in a Generic Context](https://developer.apple.com/documentation/swift/2885064-type#discussion) ⭐️
    {% endtab %}

{% tab title="📗 參考" %}

* [x] iOS 15 Programming Fundamentals with Swift (2021) - [Type Reference](http://www.apeth.com/swiftBook/ch04.html#_type_reference), p.187 ⭐️
  {% endtab %}

{% tab title="🗣 討論" %}

* [Swift - what's the difference between metatype .Type and .self?](https://stackoverflow.com/questions/31438368/swift-whats-the-difference-between-metatype-type-and-self)
  {% endtab %}
  {% endtabs %}
