什么是Metatypes?
Metatypes 是类型的类型,比如 3 是 Int 类型的实例,可以说 Int 是3的类型;那么Int的类型是啥的?Int的类型就可以称为元类型;
struct TestStruck {
static let show = "show"
func printName() { }
}
let test: TestStruck = TestStruck()
在 test: TestStruck = TestStruck()
中,我们可以说 test 是 TestStruck 的实例,而 test 的类型是 TestStruck;
我们可以通过 test 调用 printName()
方法,但是我们不能通过 test 调用 show 属性;那么我们怎样调用show 属性呢?
我们可以通过 TestStruck.show
方式调用,同样的我们也可以通过 type(of: test)
方式调用;
我们通过 type(of: )
将实例转换为可以调用对应类的所以类属性及方法的元类型;
let testType = type(of: test)
testType.show
这个时候我们可以查看一下 testType 的类型为TestStruck.Type;TestStruck.Type 就是 TestStruck 的元类型;
我们定义可以包括class、struct、enum、Protocol在内的任何类型的元类型,只需要在对应的类型名字后面调用.type,即 TestStruck.Type
type(of:) Dynamic Metatypes vs .self Static Metatypes
TestStruck.Type是元类型,那么这个类型的值什么呢?
比如String类型他的值是"string";我们可以通过 .self
获得.Type类型的值,如TestStruck.Type 类型的值为 TestStruck.self;
举例
typealias AnyClass = AnyObject.Type
UITableView 中注册cell的方法 register(AnyClass?, forCellReuseIdentifier: String)
tableView.register(MyTableViewCell.self, forReuseIdentifier: "myCell")
苹果称.self为static metatype,表示对象在编译时的类型;
type(of)为 dynamic metatype,代表在运行时对象真正的元类型;
let myNum: Any = 1 // Compile time type of myNum is Any, but the runtime type is Int.
type(of: myNum) // Int.type
Protocol Metatypes
前面说到的这些概念都适用Protocol,但是如果我们写下面的代码会报错
protocol MyProtocol {}
let metatype: MyProtocol.Type = MyProtocol.self // error
这是在 Protocol 的上下文中,MyProtocol.Type
并不代表 Protocol 自身的元类型,而是代表遵守这个协议的任何类型的元类型,苹果将其称为existential metatype(存在性元类型);
protocol MyProtocol {}
struct MyType: MyProtocol {}
let metatype: MyProtocol.Type = MyType.self // Now works!
上面的代码是正确的,这个时候 metatype 只是去访问 MyProtocol 的类方法和属性,但是实际的调用是MyType中的实现;
想要正确的获得Protocol的元类型可以通过 .protocol
,和前面提到的.Type是一样的;
let protMetatype: MyProtocol.Protocol = MyProtocol.self
其实这个时候我们并不能通过 protMetatype 做什么,大概只能做简单的 protMetatype is MyProtocol.Protocol
;