Swift -- MetaType

  • 概述

A metatype type refers to the type of any type, including class types, structure types, enumeration types, and protocol types.

元类型指的是任何类型的类型

  • class, structure, enumeration的元类型

class, structure, enumeration的元类型用类型名称加上 .Type 表示
Apple 将这种元类型称作 concrete metatypes

  • protocol的元类型

SomeProtocol.Protocol 表示的是 protocol 的元类型

SomeProtocol.Type 表示的是实现了该 protocol 的类型的元类型
Apple 将这种元类型称作 existential metatypes

SomeProtocol.self 表示的是该 protocol 的元类型的值,不能用于给 SomeProtocol.Type 赋值,只能用 SomeType.selfSomeProtocol.Type 赋值

SomeProtocol.Protocol 并没有太多实际的用处 :),应该也没有人会无聊到检查 someProtocol is SomeProtocol.Protocol :),所以我猜测 protocol 的元类型存在的意义应该是为了符合语法上的定义(其他类型都有元类型,protocol 应该也有自己的元类型),或者是为了某些编译上的需求,这个就不得而已了,留给大家慢慢探讨~

protocol SomeProtocol {
}

struct SomeStruct: SomeProtocol {
}

let metaTypeForProtocol: SomeProtocol.Protocol = SomeProtocol.self // 正确

let metaTypeForStruct: SomeProtocol.Type = SomeProtocol.self // 错误
let metaTypeForStruct: SomeProtocol.Type = SomeStruct.self // 正确
  • concrete metatypes 和 existential metatypes 的区别

通过 concrete metatypes 的值可以访问该类型的构造函数和静态成员
而通过 existential metatypes 的值仅可以访问该类型实现的协议中定义的构造函数和静态成员

  • 元类型和类型的区别

两者的区别在于:元类型的值为类型,用类型名称加上 .self 表示,而类型的值为该类型的实例对象

例如:Int.Type的值为 Int.selfInt 的值可以是任意整数

let intMetaType: Int.Type = Int.self
let intType: Int = 10

注意:SomeType.self / SomeProtocol.self 表示的是元类型的值,而 someInstance.self 表示该实例对象本身

元类型的作用

我们可以通过元类型访问该类型的构造函数

class BaseClass {
    let string: String
    init(string: String) {
        self.string = string
    }
}
let metatype: BaseClass.Type = BaseClass.self
let anotherInstance = metatype.init(string: "some string")

classprotocol 中的静态成员也是通过元类型的值来访问的,只不过XCode帮我们省略了 .self

let max1 = UInt8.max
let max2 = UInt8.self.max
// 这两种写法是等价的

type(of:) 和 .self 的区别

type(of:).self 都可以获取元类型的值,但 .self 只能获取编译时的元类型的值,即声明的类型;而 type(of:) 可以获取运行时的元类型的值,即实例对象本身具体的类型

class SomeBaseClass {
    class func printClassName() {
        print("SomeBaseClass")
    }
}
class SomeSubClass: SomeBaseClass {
    override class func printClassName() {
        print("SomeSubClass")
    }
}
let someInstance: SomeBaseClass = SomeSubClass()
// The compile-time type of someInstance is SomeBaseClass,
// and the runtime type of someInstance is SomeSubClass
type(of: someInstance).printClassName()
// Prints "SomeSubClass"

我们平时看到的 AnyClass 其实就是静态的元类型,AnyClassAnyObject.Type 的别名,而 AnyObject 是任何 class 都会默认实现的协议,所以 AnyObject.Type 的意思是 实现了AnyObject协议的class的元类型,即任意 class 的元类型。所以 AnyClass 的值可以是 SomeClass.self

public typealias AnyClass = AnyObject.Type

参考文献

What's .self, .Type and .Protocol? Understanding Swift Metatypes
Metatype Type

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。