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

What is Protocol Oriented Programming in Swift? What added value does it bring?

来自 Apple 自己的网站:"At the heart of Swift's design are two incredibly powerful ideas: protocol-oriented programming and first class value semantics."

谁能详细说明一下什么是面向协议的编程,它能带来什么附加价值?

我已经阅读了 and watched the Protocol-Oriented Programming in Swift video,但是来自 Objective-C 的背景仍然没有理解。我恳请您提供 非常 通俗易懂的英语答案,以及有关它与 Objective-C.

有何不同的代码片段和技术细节

只有 一个 我的困惑是使用 <tableViewDelegate, CustomDelegate> 我们不能也遵守 Objective-C 中的多个协议吗?那么 Swift 又是怎样的新东西呢?


编辑:参见 Protocol-Oriented Views 视频。我发现这个视频更基础,更容易掌握有意义的用例。 WWDC 视频本身有点超前,需要更大的广度。此外,这里的答案有些抽象。

前言:POP和OOP并不相互排斥。它们是非常相关的设计范例。

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

在大型继承层次结构中,祖先 classes 倾向于 包含大部分(广义)功能,叶子 classes 使只有最小的贡献。这里的问题是祖先 classes 最终做了很多事情。例如,Car 驱动、存储货物、安置乘客、播放音乐等。这些功能各不相同,但它们都不可分割地集中在 Car class 中. Car的后代,如FerrariToyotaBMW等,都对这个基class.

做了最小的修改

这样做的结果是减少了代码重用。我的 BoomBox 也可以播放音乐,但不是汽车。无法从 Car 继承音乐播放功能。

Swift 鼓励的是将这些大型整体 class 分解成更小组件的组合。然后可以更轻松地重用这些组件。 CarBoomBox 都可以使用 MusicPlayer.

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

在 Objective C 中,协议与大多数语言中的接口相同。因此在 Objective C 中,协议的使用仅限于 SOLID 原则“依赖抽象。不依赖具体。

在 Swift 中,协议得到了如此严重的改进,因为它们仍然可以用作接口,实际上它们更接近 classes(就像 C++ 中的 Abstract classes

在 Objective C 中,在 class 之间共享功能的唯一方法是继承。而你可以继承唯一的一个parentclass。在 Swift 中,您还可以采用 任意多的协议 。由于 Swift 中的协议可以具有默认方法实现,因此它们为我们提供了 fully-functional Multiple inheritance。更大的灵活性,更好的代码重用 - 太棒了!

结论:

Protocol Oriented ProgrammingOOP 基本相同,但它不仅通过继承而且通过协议更加关注功能共享采用 (Composition over inheritance)。

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

令我惊讶的是 none 的答案提到了 POP 中的值类型。

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

  1. 它(Objc)只有一个继承。如果我们有非常复杂的继承层次,底部 class 可能会有很多不必要的状态。
  2. 它使用了class,这是一个引用类型。引用类型可能导致代码不安全。例如在修改引用类型时处理它们。

在swift中进行面向协议的编程时:

  1. 它可以符合多个协议。
  2. 它不仅可以被class使用,还可以被结构枚举.
  3. 使用
  4. 它具有协议扩展,为我们提供 通用功能 所有符合协议的类型。
  5. 它更喜欢使用值类型而不是引用类型。查看标准 swift 库 here,您会发现大多数类型都是值类型的结构。但这并不意味着你根本不用 class,在某些情况下,你必须使用 class.

因此,面向协议的编程只不过是另一种试图解决 OOP 缺点的编程范例。

添加到上面的答案

Protocol 是一个接口,其中声明了方法和属性的签名,任何 class/struct/enum subclass 枚举都必须遵守合同意味着他们必须实现 superclass 协议中声明的所有方法和属性。

使用协议的原因

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

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

例子

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中假设我们有一个车辆基础class,它被飞机、自行车、汽车等继承。这里的break、acceleration可能很常见三个子class中的方法但不是飞机的可飞方法。因此,如果我们也在 OOP 中声明 flyable 方法,自行车和汽车 subclass 也有继承的 flyable 方法,这对那些 class 没有用。因此,在 POP 中,我们可以声明两个协议,一个用于可飞行对象,另一个用于中断和加速方法。并且可以限制flyable协议只能被飞机使用

面向协议编程 (POP)

  • 自 Swift 2.0
  • 以来
  • class(面向对象)
    • 是引用类型
    • 内存泄漏、存储的数据不正确、复杂多线程环境中的访问竞争条件
    • 可以通过在链时继承超级 classes 的成员来变大
  • 结构(POP)
    • 是值类型 - 每次在需要时制作新副本
    • 提供多重继承 - 继承协议
    • 协议:
    • 定义需要哪些方法、属性和初始化 o 可以 继承另一个协议
    • 不必使用 override 关键字来实现协议功能
  • 扩展:
    • 默认值和 协议
    • 的默认实现
    • 可以添加额外成员到 协议

面向协议编程(POP)

协议优先方法

  • 协议作为OOP概念的一个关键点。抽象、继承、多态、封装。
  • 作为 SOLID 基础的协议[About]
  • 协议而不是 class 层次结构树。很难支持 class 继承。此外它还有一些性能影响
  • Class/struct可以实现多个协议(一种多重继承)
  • 组合优于继承。
extension MyClass: MyProtocol {
}
  • 默认方法。所有实施者的共享实施
extension MyProtocol {
    func foo() {
        //logic
    }
}
  • 协议继承。一个协议可以扩展另一个协议。协议一的实现者应该实现所有的第一和第二协议
protocol ProtocolB: ProtocolA {
}
  • 值类型实现协议(作为通常的引用类型)[About]

什么是面向协议编程?什么是 POP?

  • 是一种新的编程范式
  • 我们通过定义协议开始设计我们的系统。我们依赖于新概念:协议扩展、协议继承和协议组合。

  • 值类型可以继承自协议,甚至是多个协议。因此,对于 POP,值类型已成为 Swift 中的第一批 class 公民。值类型,如枚举、结构 *POP 允许您使用支持多种实现的协议向 class 或结构或枚举添加功能。

  • A​​pple 告诉我们: “不要从 class 开始,要从协议开始。” 为什么?协议作为比 classes 更好的抽象。

协议:是Swift的基本特征。它们在 Swift 标准库的结构中起着主导作用,是一种通用的抽象方法。 协议用于定义“适合特定任务或功能的方法、属性和其他要求的蓝图。”

Protocol-Oriented 编程的好处:

  • 所有 classes 相互解耦
  • 将声明与实现的关注点分开
  • 可重用性
  • 可测试性