protocol Drawable { func draw() var x: Int { get set } var y: Int { get } subscript(index: Int) -> Int { get } } class Person: Drawable { var x: Int = 0 let y: Int = 10 func draw() { print("Person draw") } subscript(index: Int) -> Int { return index } } 复制代码
protocol P1 { } protocol P2 { } class Person { } func fn0(obj: P1 & P2 & Person) { } 复制代码
enum Season { case spring, summer, autumn, winter } extension Season: CaseIterable { } func test34() { let seasons = Season.allCases print(seasons) } 复制代码
(stu as? Student)?.study() // 转化有可能会失败,失败的时候方法不调用 (stu as? Student)!.study() // 转化有可能会失败,但也强制解包,所以有可能发生闪退 (stu as! Student).study() // 和上面的完全等价,可以看成是上面这种写的简写 复制代码
as 在编译器层面就能确保你转换是一定能够成功的了 var d = 10 as Double 复制代码
class Person { } class Student: Person { } let person = Person() var perType: Person.Type = Person.self let stuType: Student.Type = Student.self perType = Student.self var anyType: AnyObject.Type = Person.self anyType = Student.self // public typealias AnyClass = AnyObject.Type var anyType2: AnyClass = Person.self anyType2 = Student.self ---------------------汇编分析--------------------- register read rax rax = 0x0000000100014e48 type metadata for Person #1 in swiftstudy.test36() -> () (lldb) register read rax rax = 0x0000000102900000 (lldb) x/5wg 0x0000000102900000 0x102900000: 0x0000000100014e48 0x0000000000000002 0x102900010: 0x0000000000000000 0x0000000000000000 0x102900020: 0x2f6d657473790017 复制代码
从上面的汇编也验证了,其实X.self就是一个元类型(metadata)指针
class Person { var age: Int = 0 } class Student: Person { var no: Int = 0 } print(class_getInstanceSize(Person.self)) print(class_getSuperclass(Student.self)!) print(class_getSuperclass(Person.self)!) ---------------------汇编分析--------------------- 24 Person _TtCs12_SwiftObject 复制代码
可以看出来, Swift 还有个隐藏的基类:Swift.__SwiftObject,其实他和 oc 一样,前8个字节存的也是 isa 指针(就是用于查找他的类信息的),其实也可以理解,打印所有的纯 swift 对象,可以发现一个规律,就是前8个字节存储 isa,后面跟着8个字节存储引用计数,把他们抽成一个父类其实更合理。
class Person { required init() { } func test() -> Self { Self.self.init() } func test1() -> Self { Self.self.init() } } class Student: Person { } let p = Person().test().test1() 复制代码
type(of: p) == Person.self? type(of: p) 和 sizeof 这种是一样的,本质不是调用函数,只是将 p 的前8个字节取出来,所以 type(of: p)和 Person.self 是相等的
Person 和 Person.self 的异同
class Person { static var age = 0 static func run() {} } Person.age = 10 Person.self.age = 20 func test(_ cls: AnyClass) { } test(Person.self) 复制代码
也就是说当你明确需要传 X.Type 的时候,这个时候X.self,不然用类名一般就够用了