在讲解Self之前,需要先简短介绍一下type(of:)的用法。
type(of:)
从Xcode 8 beta 6开始,dynamicType
被替换为了type(of:)
。(SE-0096)
type(of:)
的功能是获得实例在运行时(runtime)的元类型(meta type)。这个在之前的Swift里,被称作是dynamicType
,与静态的类型进行区别。
Self
Self
是一个特殊的类型。它是self对应的类型。而self是动态类型。比如:
class Foo {
func printType() {
print(type(of:self))
}
func printSelf() {
print(self)
}
}
class Bar:Foo {
}
let foo = Foo()
foo.printType() // Foo
foo.printSelf() // Foo
let bar = Bar()
bar.printType() // Bar
bar.printSelf() // Bar
var test = Foo()
test.printType() // Foo
test.printSelf() // Foo
test = Bar()
test.printType() // Bar
test.printSelf() // Bar
可以看到,self
始终对应的是实际类型,无论变量的类型是Foo还是Bar。
由于这个特性的存在,这使得Self无法从静态类型进行转换,而只能通过self来生成。即:
class Foo {
func bar() -> Self {
return self
}
}
class Foo1 {
func bar1() -> Self {
return type(of:self).init()
}
required init() { }
}
注意
Foo1中,有一个
required init()
,这是type(of:self).init()
必须的。
Self
的使用有以下方式:
1. 在协议的返回值中使用
这是最常见的使用方式。
protocol Foo {
func instance() -> Self
}
class Bar: Foo {
func instance() -> Self {
return self // Declaration: let `self`: Self
}
func other() {
let i = self // Declaration: let `self`: Bar
}
}
class otherBar:Foo {
func instance() -> Self {
return type(of:self).init()
}
required init() { }
}
####注意
Bar中的实现协议的函数里,self是Self类型。而非Self返回值的函数里,self是所在类的类型。
可以使用type(of:self).init()
,获得一个新的Self实例。此时,类中必须要有一个required init()
。
Self作为函数的返回值的类型时,可以直接写在类中,而不必非要有协议。
下面2和3中的情形,使用associateType
的效果,要好于Self。因此,1是Self的最常用的方式。
2. 在协议的函数的参数类型中使用
protocol Foo {
func bar(b:Self)
}
class Bar:Foo {
func bar(b:Bar) {
print(b)
}
}
####注意
Bar中的func bar(b:Bar)
是Bar而不是Self。但是这满足协议。这也符合类的多态,即Bar的子类可以调用这个函数。
3. 在协议的属性里使用
protocol Foo {
var bar:Self { get set }
}
final class Bar:Foo {
var bar: Bar
init(b:Bar) {
self.bar = b
}
}
####注意
在协议的属性里使用Self时,类必须时final类。
###参考文献:
以下参考文献的一些代码针对的是3.0版本之前的Swift。部分内容需要修正才能运行。但基本原理是相同的。
Types and meta types in swift
Swift中你应该知道的一些有用的tips
Generic Protocols & Their Shortcomings 这篇难度较高,慎看。
Self in Protocol and class method