发布于 2015-06-14 01:45:42 | 224 次阅读 | 评论: 0 | 来源: 网络整理
可选协议含有可选成员,其遵循者
可以选择是否实现这些成员。在协议中使用@optional
关键字作为前缀来定义可选成员。
可选协议在调用时使用可选链
,详细内容在可选链章节中查看。
像someOptionalMethod?(someArgument)
一样,你可以在可选方法名称后加上?
来检查该方法是否被实现。可选方法
和可选属性
都会返回一个可选值(optional value)
,当其不可访问时,?
之后语句不会执行,并返回nil
。
注意: 可选协议只能在含有@objc
前缀的协议中生效。且@objc
的协议只能被类
遵循。
Counter
类使用CounterDataSource
类型的外部数据源来提供增量值(increment amount)
,如下所示:
@objc protocol CounterDataSource {
@optional func incrementForCount(count: Int) -> Int
@optional var fixedIncrement: Int { get }
}
CounterDataSource
含有incrementForCount
的可选方法
和fiexdIncrement
的可选属性
。
注意:CounterDataSource
中的属性和方法都是可选的,因此可以在类中声明但不实现这些成员,尽管技术上允许这样做,不过最好不要这样写。
Counter
类含有CounterDataSource?
类型的可选属性dataSource
,如下所示:
@objc class Counter {
var count = 0
var dataSource: CounterDataSource?
func increment() {
if let amount = dataSource?.incrementForCount?(count) {
count += amount
} else if let amount = dataSource?.fixedIncrement? {
count += amount
}
}
}
count
属性用于存储当前的值,increment
方法用来为count
赋值。
increment
方法通过可选链
,尝试从两种可选成员
中获取count
。
dataSource
可能为nil
,因此在dataSource
后边加上了?
标记来表明只在dataSource
非空时才去调用incrementForCount`方法。dataSource
存在,但是也无法保证其是否实现了incrementForCount
方法,因此在incrementForCount
方法后边也加有?
标记。在调用incrementForCount
方法后,Int
型可选值
通过可选绑定(optional binding)
自动拆包并赋值给常量amount
。
当incrementForCount
不能被调用时,尝试使用可选属性``fixedIncrement
来代替。
ThreeSource
实现了CounterDataSource
协议,如下所示:
class ThreeSource: CounterDataSource {
let fixedIncrement = 3
}
使用ThreeSource
作为数据源开实例化一个Counter
:
var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 {
counter.increment()
println(counter.count)
}
// 3
// 6
// 9
// 12
TowardsZeroSource
实现了CounterDataSource
协议中的incrementForCount
方法,如下所示:
class TowardsZeroSource: CounterDataSource {
func incrementForCount(count: Int) -> Int {
if count == 0 {
return 0
} else if count < 0 {
return 1
} else {
return -1
}
}
}
下边是执行的代码:
counter.count = -4
counter.dataSource = TowardsZeroSource()
for _ in 1...5 {
counter.increment()
println(counter.count)
}
// -3
// -2
// -1
// 0
// 0