Swift(十一) 协议

协议

语法

类、结构体、枚举都可遵循协议

1
2
3
protocol SomeProtocol {
// 协议内容
}

类或结构体遵循协议

1
2
3
struct SomeStructure: FirstProtocol, AnotherProtocol {
// 结构体内容
}

对属性规定

协议可以规定其遵循者提供特定名称和类型的实例属性(instance property)或类属性(type property),而不用指定是存储型属性(stored property)还是计算型属性(calculate property)。此外还必须指明是只读的还是可读可写的。

1
2
3
4
5
6
7
protocol SomeProtocol {
var mustBeSettable : Int { get set }
var doesNotNeedToBeSettable: Int { get }
// 类型属性
static var someTypeProperty: Int { get set }

}

对方法的规定

1
2
3
4
protocol SomeProtocol {
static func someTypeMethod()
func someInstanceMethod()
}

对 Mutating 方法的规定

结构体和枚举是值类型。一般情况下,值类型的属性不能在它的实例方法中被修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

protocol ExProtocol1 {

mutating func toggle()
}

enum OnOffSwitch: ExProtocol1 {
case Off, On
mutating func toggle() {
switch self {
case Off:
self = On
case On:
self = Off
}
}
}
var lightSwitch = OnOffSwitch.Off
lightSwitch.toggle()

对构造器的规定

1
2
3
protocol SomeProtocol {
init(someParameter: Int)
}

协议构造器在类中的实现

1
2
3
4
5
6

class SomeClass: SomeProtocol {
required init(someParameter: Int) {
//构造器实现
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protocol SomeProtocol {
init()
}

class SomeSuperClass {
init() {
// 构造器的实现
}
}

class SomeSubClass: SomeSuperClass, SomeProtocol {
// 因为遵循协议,需要加上"required"; 因为继承自父类,需要加上"override"
required override init() {
// 构造器实现
}
}

协议类型

  • 作为函数、方法或构造器中的参数类型或返回值类型
  • 作为常量、变量或属性的类型
  • 作为数组、字典或其他容器中的元素类型

扩展中添加协议成员

即便无法修改源代码,依然可以通过扩展(Extension)来扩充已存在类型(译者注: 类,结构体,枚举等)。扩展可以为已存在的类型添加属性,方法,下标脚本,协议等成员

通过扩展补充协议声明

当一个类型已经实现了协议中的所有要求,却没有声明为遵循该协议时,可以通过扩展(空的扩展体)来补充协议声明

协议继承

1
2
3
4

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
// 协议定义
}

类专属协议

1
2
3
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
// 协议定义
}

协议合成

protocol <AProtocol, BProtocol>

可选协议

optional 方法

见Xcode

1
2
3
4
5
6
7
8
9

protocol MyClassDelegate {
func method()
}

class MyClass {
weak var delegate: MyClassDelegate?
}
// 编译器会报错

由于swift中的结构体、枚举等值类型可以遵守协议,而值类型不通过引用计数来管理内存,所以不能用weak这种ARC的概念来修饰。

解决方法 将协议声明为Objc的或者将协议声明为只能由类来实现。

协议扩展

使用扩展协议的方式为协议的遵循者提供方法或属性的实现。通过这种方式,可以让你无需在每个遵循者中都实现一次,无需使用全局函数,你可以通过扩展协议的方式进行定义。

如果遵循者自己实现了协议规定的方法,那么遵循者的实现方法将被使用。

为协议扩展添加限制条件

1
2
3
4
5
6
extension CollectionType where Generator.Element : TextRepresentable {
var textualDescription: String {
let itemsAsText = self.map { $0.textualDescription }
return "[" + itemsAsText.joinWithSeparator(", ") + "]"
}
}