顾名思义,Protocol Extension就是对接口的扩展,这个是在Swift 2 中引入的一个非常重要的特性。在 protocol 不能被扩展的时候,当我们想要为实现了某个接口的所有类型添加一些另外的共通的功能时,会非常麻烦。在 Swift 2 中这个问题被彻底解决了。现在我们可以对一个已有的 protocol 进行扩展,而扩展中实现的方法将作为实现扩展的类型的默认实现。
protocol A1 {
func method1() -> String
}
class B1: A1 {
func method1() -> String {
return "Hello"
}
}
let b1 = B1()
b1.method1() // Hello
let a1: A1 = B1()
a1.method1() // Hello
毋庸置疑,这里都会输出Hello
。
我们把method1
的实现放在接口的扩展中。
protocol A1 {
func method1() -> String
}
extension A1 {
func method1() -> String {
return "Hello"
}
}
class B1: A1 {
}
let b1 = B1()
b1.method1() // Hello
let a1: A1 = B1()
a1.method1() // Hello
在具体的实现这个接口的类型中,即使我们什么都不写,也可以编译通过。进行调用的话,会直接使用 extension 中的实现。
但是如果在接口里只定义了一个方法,而在接口扩展中实现了额外的方法的话,事情就变得有趣起来了。
protocol A2 {
func method1() -> String
}
extension A2 {
func method1() -> String {
return "hi"
}
func method2() -> String {
return "hi"
}
}
class B2: A2 {
func method1() -> String {
return "Hello"
}
func method2() -> String {
return "Hello"
}
}
let b2 = B2()
b2.method1() // Hello
b2.method2() // Hello
let a2: A2 = B2()
a2.method1() // Hello
a2.method2() // hi
规则总结:
- 如果类型推断得到的是实际的类型
- 那么类型中的实现将被调用;如果类型中没有实现的话,那么接口扩展中的默认实现将被使用
- 如果类型推断得到的是接口,而不是实际类型
- 并且方法在接口中进行了定义,那么类型中的实现将被调用;如果类型中没有实现,那么接口扩展中的默认实现被使用
- 否则 (也就是方法没有在接口中定义),扩展中的默认实现将被调用