美文网首页
Introducing Protocol-Oriented Pr

Introducing Protocol-Oriented Pr

作者: __pencilCool__ | 来源:发表于2016-12-11 08:03 被阅读17次

    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
      }
    }
    

    相关文章

      网友评论

          本文标题:Introducing Protocol-Oriented Pr

          本文链接:https://www.haomeiwen.com/subject/tznymttx.html