`

记Protocol Oriented Programming in Swift of WWDC 2015

阅读更多
其实最先朋友让我就这个题目写篇文章的时候,我是拒绝的,因为觉得苹果就是在炒冷饭, 把已经流行了数十年的OOP中的“面向接口编程”还拿来讲,看完整个Session之后呢,虽然还是觉得在炒冷饭,但是毕竟还是加了蛋的,有些东西还是值得说说的。

通常谈到面向接口编程,其主要作用是把系统设计和具体实现分离开,让系统的每个部分都可以在不影响别的部分的情况下,改变自身的具体实现。接口的设计就反映了系统设计人员对系统的抽象理解。

而苹果在除了把Interface名字换为Protocol之外,还在这个理念上添加了怎样的鸡蛋呢?

Self Requirement

第一个蛋:学名叫做Self Requirement,主要的作用就是解决使用Protocol(接口)之后,类型缺失的问题,即,当在对象类型上使用了protocol类型之后,如果还需要调用对象自有的一些方法,那么就不得不用as!做一个强制类型转换。

Talk is cheap, Let's show the code

假设我们要实现一个通用的二分查找函数,如下:
protocol Ordered {
    func precedes(other: Ordered) -> Bool
}

func binarySearch(sortedKeys: [Ordered], forKey k: Ordered) -> Int {
    var lo = 0, hi = sortedKeys.count
    while hi > lo {
        let mid = lo + (hi - lo) / 2
        if sortedKeys[mid].precedes(k) {
            lo = mid + 1
        } else {
            hi = mid
        }
    }
    return lo
}
任何实现了Ordered protocol的对象(包括class,struct和enum)都可以使用该函数做二分查找。下面我们就来看看一个实现了Ordered协议Number类的代码:

class Number : Ordered {
  var value: Double = 0
  func precedes(other: Ordered) -> Bool {
        return value < (other as! Number).value // Warning!!! as!的使用就是丢失类型信息的信号。
  }
}
而通过Self requirement特性,可以在protocol中使用Self来指代实现这个接口的具体类,如下:
protocol Ordered {
    func precedes(other: Self) -> Bool
}
在具体的实现类中,就可以像下面这样实现:

class Number : Ordered {
  var value: Double = 0
  func precedes(other: Number) -> Bool {
        return value < other.value 
  }
}
最后,需要注意的是,一旦在protocol中使用了Self,那么该protocol就不能做类型限定符了,即不能再使用该类型指定参数,属性的类型,其只能用于泛型中。因此,需要把最先的二分查找函数修改如下:
func binarySearch<T:Ordered>(sortedKeys: [T], forKey k: T) -> Int {
    var lo = 0, hi = sortedKeys.count
    while hi > lo {
        let mid = lo + (hi - lo) / 2
        if sortedKeys[mid].precedes(k) {
            lo = mid + 1
        } else {
            hi = mid
        }
    }
    return lo
}

通过这个特性,可以让代码更加清晰,隔离性更好,处理Number时,只需要在意Number而无需去考虑其它的实现了Ordered的对象。同时,因为整个程序运行时的类型都是固定的,对编译器优化程序也有很大的帮助。

Protocol Extension,

第二个大鸡蛋:学名叫做Protocol Extension。 在使用接口时,经常会出现如下的场景,几个类实现了同一个接口,接口的其中一个方法,在几个类中实现都是一样的。这个时候就会出现几个类有重复代码的情形,一般有2种方式来消除掉这种重复,一是给这几个毫无关系的类加一个共同父类来做代码共享(强烈建议不要这样做);二是把这个方法抽出到一个单独的类中,再通过组合方式把功能引回需要使用的类(比较麻烦)。而protocol extension就完美的解决了这样的问题。如下:

定义一个protocol:
import CoreGraphics
protocol Renderer {
  func circleAt(center: CGPoint, radius: CGFloat)
  func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat)
}

如果协议中的某个方法,比如说circleAt,所有实现类的实现都是一样的, 那么可以做一个protocol extension,添加该方法的默认实现:
extension Renderer {
  func circleAt(center: CGPoint, radius: CGFloat) {
    print("protocol circleAt")
  }
}

另外,如果几个类中,大部分都通用,就只有1,2个类实现方式不一样,protocol extension同样可以处理,只需要在类中实现自己想要的行为就行了:
struct Circle : Renderer {
    func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) {
        print("Circle arcAt")
    }

    func circleAt(center: CGPoint, radius: CGFloat) {
        print("Circle circleAt")
    }
}

struct Triangle : Renderer {
    func arcAt(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat) {
        print("Triangle arcAt")
    }
}

程序在执行时,会先从当前类中查找想要的方法,没找到才会继续向上查找protocol extension中的默认实现。如下:
func test(r:Renderer) {
        r.circleAt(CGPoint(x: 1, y: 1), radius: 1.2)
}

test(Circle()) //会打印Circle circleAt
test(Triangle()) //会打印protocol circleAt

除了上面提到的之外,Protocol Extension还提供了一个有趣的特性:

限制扩展支持的类型 :即你可以在实现Protocol Extension时,直接指定必须满足某种条件才能使用该扩展中的方法,前面提到的是子类决定要不要接受Protocol Extensio中的默认实现,而这个特性是Protocol Extension设置默认实现的使用门槛。 比如:只有集合中的对象支持Equatable才能使用默认indexOf方法:
extension CollectionType where Generator.Element : Equatable {
    public func indexOf(element: Generator.Element) -> Index? {
        for i in self.indices {
            if self[i] == element {
                return i
            }
        }
        return nil
    }
}

有了这个特性,就可以重新组合方法定义的位置,并把泛型抽取到定义扩展时,从而使得方法的定义更加清晰,也更加美观,如下:

美颜前
func binarySearch<C : CollectionType where C.Index == RandomAccessIndexType, C.Generator.Element : Ordered >(sortedKeys: C, forKey k: C.Generator.Element) -> Int {
  ...
}

let pos = binarySearch([2, 3, 5, 7, 11, 13, 17], forKey: 5)

美颜后
extension CollectionType where Index == RandomAccessIndexType, Generator.Element : Ordered {
  func binarySearch(forKey: Generator.Element) -> Int {
    ...
  } 
}

let pos = [2, 3, 5, 7, 11, 13, 17].binarySearch(5)


总结

从上面的讲述,可以看得出来,Swift2.0带来的Protocol Extension算是针对使用面向接口编程遇到的各种问题提供了一个比较用心的解决方案, 因此,在Swift使用Protocol Oriented Pragraming是一个非常不错的选择,整个思维模式和以前的面向接口编程并无多大的差别,同时还可以享受到苹果提供的这些贴心小特性, 你已经比大Java程序员幸福多了。
2
2
分享到:
评论

相关推荐

    Swift 4 Protocol-Oriented Programming(3rd) epub

    Swift 4 Protocol-Oriented Programming(3rd) 英文epub 第3版 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除

    Protocol.Oriented.Programming.with.Swift.1785

    Swift的设计核心包含了极其强大的概念:协议导向编程(Protocol-Oriented Programming)。这一理念带来了诸多好处,包括更好的代码可维护性、提高开发者生产力以及更优秀的应用性能。本书将教授读者如何应用协议导向...

    Swift 4 Protocol-Oriented Programming, 3rd Edition

    Leverage the power of protocol-oriented programming in your applications and learn from real-world use cases Create a flexible code base with protocols and protocol extensions Leverage the power of ...

    Protocol Oriented Programming (Swift 4)

    面向协议编程(Protocol Oriented Programming,简称POP)是Swift 3.0以后由Apple提出的一种编程理念。这种编程范式充分利用了Swift语言的特点,比如协议扩展、协议继承等,与传统的面向对象编程(Object Oriented ...

    Swift 4 Protocol-Oriented Programming, 3rd Edition-Packt Publishing(2017).pdf

    When Apple announced Swift 2 at the World Wide Developers Conference (WWDC) in 2015, they also declared that Swift was the world's first protocol-oriented programming language. By its name, we may ...

    高清彩版 Swift 4 Protocol-Oriented Programming(Swift 4)

    ### Swift 4 Protocol-Oriented Programming #### 一、概览与背景介绍 《Swift 4 Protocol-Oriented Programming》是一本深入探讨Swift语言中协议导向编程(Protocol-Oriented Programming, POP)技术的书籍。本书...

    Swift.3.Protocol-Oriented.Programming.2nd.Edition.epub

    Leverage the power of protocol-oriented programming in your applications and learn from real world use cases Create a flexible codebase with protocols and protocol extensions Increase the overall ...

    Swift 3 Protocol-Oriented Programming(2nd) azw3

    Swift 3 Protocol-Oriented Programming(2nd) 英文azw3 第2版 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除

    Swift Protocol-Oriented Programming.zip

    Swift Protocol-Oriented Programming是Jon Hoffman撰写的一本深入探讨Swift编程语言中协议导向编程(POP)的资源。Swift 5版本的更新为POP提供了更强大的支持,使得这一编程范式在实际开发中更加灵活和实用。POP的...

    Swift 3 Protocol-Oriented Programming(2nd) mobi

    Swift 3 Protocol-Oriented Programming(2nd) 英文mobi 第2版 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除

    Swift 4 Protocol-Oriented Programming(3rd) azw3

    Swift 4 Protocol-Oriented Programming(3rd) 英文azw3 第3版 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除

    Swift 4 Protocol-Oriented Programming(3rd) 无水印原版pdf

    Swift 4 Protocol-Oriented Programming(3rd) 英文无水印原版pdf 第3版 pdf所有页面使用FoxitReader、PDF-XChangeViewer、SumatraPDF和Firefox测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn...

    Packt.Swift.4.Protocol-Oriented.Programming.3rd.Edition.2017

    ### Swift 4 Protocol-Oriented Programming 第三版 #### 核心知识点概览 本教材《Swift 4 Protocol-Oriented Programming》第三版由 Packt Publishing 出版于2017年,作者为 Jon Hoffman。本书深入探讨了 Swift ...

    Swift 3 Protocol-Oriented Programming(2nd) 无水印pdf

    Swift 3 Protocol-Oriented Programming(2nd) 英文无水印pdf 第2版 pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如...

    Packt.Swift.Functional.Programming.2nd.Edition.2017

    Develop a case study on example backend API with Swift and Vapor Framework and an iOS application with Functional Programming, Protocol-Oriented Programming, Functional Reactive Programming, and ...

    《Object-Oriented Programming with Object C》 英文高清原版 PDF

    《Object-Oriented Programming with Object C》是一本深入探讨面向对象编程(OOP)与Objective-C语言的专业书籍。Objective-C是Apple开发的一种强大的、面向对象的编程语言,主要用于iOS和macOS的应用程序开发。这...

Global site tag (gtag.js) - Google Analytics