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

什么是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")

苹果称.selfstatic 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;

资料引用

Apple Types

blog

你可能感兴趣的:(What's .self, .Type and .Protocol? Understanding Swift Metatypes)