什么是Swift中的面向协议编程?它带来了什么附加价值?

时间:2016-05-30 16:40:20

标签: objective-c oop swift2 protocols delegation

来自Apple自己的网站:" Swift设计的核心是两个非常强大的想法:面向协议的编程和一流的价值语义。 #34;

有人可以详细说明什么是面向协议的编程,它带来了什么附加价值?

我已阅读this并观看了Swift video中的面向协议编程,但来自Objective-C背景仍然无法理解。我恳请一个非常简单的英语答案以及代码片段&关于它与Objective-C的不同之处的技术细节。

只是我所使用的混淆中的一个 <tableViewDelegate, CustomDelegate>我们也不能符合Objective-C中的多个协议吗?那么Swift又是如何新的?

编辑:请参阅Protocol-Oriented Views视频。我发现这个视频更基本,更容易掌握一个有意义的用例。 WWDC视频本身有点先进,需要更广泛的视野。此外,这里的答案有点抽象。

5 个答案:

答案 0 :(得分:31)

前言:POP和OOP不是互斥的。他们的设计范式非常相关。

POP over OOP的主要方面是更喜欢composition over inheritance。这有几个好处。

在大型继承层次结构中,祖先类倾向于以包含大多数(通用)功能,而叶子类只产生最小的贡献。这里的问题是祖先类最终会做很多事情。例如,一个Car驱动器,存储货物,安排乘客,播放音乐等。这些是许多功能,每个功能都非常不同,但它们都不可分割地归入Car类。 Car的后代,例如FerrariToyotaBMW等,都对此基类进行了少量修改。

这样做的结果是减少了代码重用。我的BoomBox也播放音乐,但它不是汽车。

Swift鼓励的是,这些庞大的整体类被分解为更小的组件。然后可以更容易地重用这些组件。 CarCar都可以使用BoomBox

Swift提供了多种功能来实现这一目标,但到目前为止最重要的是协议扩展。它们允许协议的实现与其实现类分开存在,因此许多类可以简单地实现该协议并立即获得其功能。

答案 1 :(得分:9)

在Objective C协议中,与大多数语言中的接口相同。因此,在Objective C协议中,使用仅限于SOLID原则&#34; 依赖于抽象。不要依赖于结核。&#34;

在Swift中,协议的改进非常严重,因为它们仍然可以用作接口,实际上它们更接近类(如C ++中的Abstract classes

在Objective C中,在类之间共享功能的唯一方法是继承。并且您可以继承唯一的一个父类。在Swift中,你也可以采用任意数量的协议。由于Swift中的协议可以使用默认方法实现,因此它们为我们提供了一个功能齐全的Multiple inheritance。更灵活,更好的代码重用 - 太棒了!

<强>结论:

面向协议的编程 OOP 大致相同,但它不仅通过继承而且通过协议采用(Composition over inheritance)进一步关注功能共享。

值得一提的是,在C ++中,抽象类与Swift中的协议非常相似,但没有人说C ++支持某种特定类型的OOP。因此,在 general 中,如果我们谈论编程范例,POP就是OOP的一个版本。对于Swift,POP是OOP的改进版本。

答案 2 :(得分:8)

令我感到惊讶的是,没有一个答案提到POP中的值类型。

要了解什么是面向协议的编程,您需要了解面向对象编程的缺点。

  1. 它(Objc)只有一个继承。如果我们有非常复杂的继承层次结构,那么底层类可能有很多不必要的状态。
  2. 它使用作为参考类型的类。引用类型可能导致代码不安全。例如在修改引用类型时处理它们的集合。
  3. 在swift中面向协议的编程中:

    1. 它可以符合多个协议。
    2. 它不仅可以用于课程,还可以用于结构枚举
    3. 它具有协议扩展功能,可为所有符合协议的类型提供通用功能
    4. 它更喜欢使用值类型而不是引用类型。看一下标准的swift库here,你可以发现大多数类型都是值类型的结构。但这并不意味着你根本不使用类,在某些情况下,你必须使用类。
    5. 因此,面向协议的编程只不过是另一种尝试解决OOP缺点的编程范式。

答案 3 :(得分:4)

添加上述答案

协议是一个接口,其中声明方法和属性的签名,并且枚举枚举的任何class / struct / enum必须遵守合同意味着它们必须实现声明的所有方法和属性在超类协议中。

使用协议的原因

类提供单继承,而struct不支持继承。因此引入了协议。

扩展协议内部声明的方法可以在扩展内部实现,以避免在具有相同方法实现的多个类/结构中继承协议的情况下代码的冗余。我们可以通过简单地声明struct / enums的对象来调用该方法。即使我们可以将扩展限制为类列表,只有受限类才能使用扩展内部实现的方法,而其余的类必须在自己的类中实现方法。

示例

protocol validator{

    var id : String{ get }
    func capitialise()-> (String)

}

extension validator where Self : test{
    func capitialise() -> String{
        return id.capitalized
    }
}

class test : validator {

    var id: String

    init(name:String) {
        id = name
    }
}

let t = test(name: "Ankit")
t.capitialise()

何时使用在OOP中假设我们有一个由飞机,自行车,汽车等继承的车辆基类。这里打破,加速可能是三个子类中的常用方法,但不是可飞行方法飞机因此,如果我们也在OOP中声明可飞行方法,那么自行车和汽车子类也具有继承可飞行方法,这对于那些类没用。因此在POP中我们可以声明两个协议,一个用于可飞行对象,另一个用于中断和加速方法。可飞行协议可以限制仅由飞机使用

答案 4 :(得分:0)

面向协议的编程(POP)

  • 自Swift 2.0起加入
  • 类(OOP)
    • 是引用类型
    • 内存泄漏,错误存储的数据,在复杂的多线程环境中访问的条件
    • 在链接时继承超类的成员可能会很大
  • 结构(POP)
    • 是值类型-每次在需要时制作新副本
    • 提供多继承-继承协议
    • 协议:
    • 定义所需的方法,属性和初始化o 继承另一个协议
    • 不必使用override关键字即可实现协议功能
  • 扩展名:
    • 默认值和 协议的默认实现
    • 可以向添加更多成员 协议