# 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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lochiwei.gitbook.io/ios/swift/debugging/metatype.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
