link
协议的扩展,可以根据实现这个协议的对象的实际情况(有无实现其他协议)来设置协议的默认值。:
protocol Bird {
var name: String { get }
var canFly: Bool { get }
}
protocol Flyable {
var airspeedVelocity: Double { get }
}
extension Bird {
// Flyable birds can fly!
var canFly: Bool {
return self is Flyable
}
}
为什么不用基类
protocol extensions do not introduce any additional state.
也就是说协议扩展不能添加新的变量???
protocol Bird {
var name: String { get }
var canFly: Bool { get }
}
extension Bird {
// Flyable birds can fly!
var test: String {
return "heheda"
}
var canFly: Bool {
return true
}
}
struct bigBird: Bird{
var name: String {
return "big bird"
}
}
let a = bigBird()
print(a.name)
print(a.test)
print(a.canFly)
big bird
heheda
true
发现能在扩展中添加变量呀。没有引入其他的状态怎么理解?
???
当然protocol相比基类,应用范围广:结构体,枚举,都能用。
修改对象中协议的默认实现。 ---> 对这个对象进行extension:
extension UnladenSwallow {
var canFly: Bool {
return self != .unknown
}
}
给实现了协议的部分对象添加新的方法
extension CustomStringConvertible where Self: Bird {
var description: String {
return canFly ? "I can fly" : "Guess I’ll just sit here :["
}
}
在swift 标准库里发挥效用
让类型稍有不同的对象(通常这些对象关系和密切,是可以互相转化的) 拥有相同的方法。
协议能让不同的对象具有相同的可比较的属相。
比如汽车,鸟类都有移动速度这个共同属相。
可以用这用的方法来求取得这些不同对象的共同属性的比较结果:
func topSpeed(of racers: [Racer]) -> Double {
return racers.max(by: { $0.speed < $1.speed })?.speed ?? 0
}
topSpeed(of: racers) // 3000
这里的局限是针对的是实现了Racer协议的数组,更加一般的形式是,实现了Racer协议的 Sequence 类型对象。所有用到泛型来定义:
func topSpeed<RacerType: Sequence>(of racers: RacerType) -> Double
where RacerType.Iterator.Element == Racer {
return racers.max(by: { $0.speed < $1.speed })?.speed ?? 0
}
主要到这个套路:
规定sequence 中元素的类型
RacerType.Iterator.Element == Racer
更进一步的优化:
extension Sequence where Iterator.Element == Racer {
func topSpeed() -> Double {
return self.max(by: { $0.speed < $1.speed })?.speed ?? 0
}
}
racers.topSpeed() // 3000
racers[1...3].topSpeed() // 42
总结一下演进过程
- 构造针对具有相同属性的对象{数组形式}的处理函数
参数:[协议]
- 将函数的接受对象的范围从数组形式到sequence形式。
泛型:sequence协议 {指出 满足sequence 的泛型 ,他其中的元素 满足协议 (你要操作的属性)}
- 直接将这个协议(定义共同通属性) 放入sequence 的协议扩展中。
刚刚做的是对一组具有相同属性的不同对象之间的比较,那如果是在同类对象之间的比较呢?
protocol Score: Equatable, Comparable {
var value: Int { get }
}
struct RacingScore: Score {
let value: Int
static func ==(lhs: RacingScore, rhs: RacingScore) -> Bool {
return lhs.value == rhs.value
}
static func <(lhs: RacingScore, rhs: RacingScore) -> Bool {
return lhs.value < rhs.value
}
}
网友评论