什么是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 調(diào)用 printName() 方法,但是我們不能通過 test 調(diào)用 show 屬性;那么我們怎樣調(diào)用show 屬性呢?
我們可以通過 TestStruck.show 方式調(diào)用,同樣的我們也可以通過 type(of: test) 方式調(diào)用;
我們通過 type(of: ) 將實例轉(zhuǎn)換為可以調(diào)用對應(yīng)類的所以類屬性及方法的元類型;
let testType = type(of: test)
testType.show
這個時候我們可以查看一下 testType 的類型為TestStruck.Type;TestStruck.Type 就是 TestStruck 的元類型;
我們定義可以包括class、struct、enum、Protocol在內(nèi)的任何類型的元類型,只需要在對應(yīng)的類型名字后面調(diào)用.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 自身的元類型,而是代表遵守這個協(xié)議的任何類型的元類型,蘋果將其稱為existential metatype(存在性元類型);
protocol MyProtocol {}
struct MyType: MyProtocol {}
let metatype: MyProtocol.Type = MyType.self // Now works!
上面的代碼是正確的,這個時候 metatype 只是去訪問 MyProtocol 的類方法和屬性,但是實際的調(diào)用是MyType中的實現(xiàn);
想要正確的獲得Protocol的元類型可以通過 .protocol,和前面提到的.Type是一樣的;
let protMetatype: MyProtocol.Protocol = MyProtocol.self
其實這個時候我們并不能通過 protMetatype 做什么,大概只能做簡單的 protMetatype is MyProtocol.Protocol;