-
概述
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.self 给 SomeProtocol.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.self,Int 的值可以是任意整数
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")
class 或 protocol 中的静态成员也是通过元类型的值来访问的,只不过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 其实就是静态的元类型,AnyClass 是 AnyObject.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