ios - 面向协议(protocol)的编程不会带来继承主要解决的代码重复问题吗?

标签 ios swift inheritance protocols

概览

我试图了解 Swift 的面向协议(protocol)编程范式。根据 Apple 的 WWDC 2015 视频 https://developer.apple.com/videos/play/wwdc2015/408/协议(protocol)可以实现继承所能实现的一切,也解决了继承的根本问题。

虽然协议(protocol)通过将每个能力(功能)捕获为协议(protocol)并允许类/结构确认多个协议(protocol)来解决多重继承问题,但我认为协议(protocol)永远不能取代继承,原因如下。

假设我正在实现学院/学校自动化软件,并且有两个实体,教职工和校长,并假设他们都上课,但校长和上课一起控制教职工。

因此,我创建了一个协议(protocol),该协议(protocol)将对正在类的通用功能进行建模。因此,让我们创建一个协议(protocol)。

protocol staffProtocol {
    var classHour : Int { get set}
    var numberOfClass : Int? { get set }

    mutating func doesWork()
}

extension staffProtocol {
    mutating func doesWork(){
        classHour = 9
        numberOfClass = 4
        print("Takes calss")
    }
}

因为上课是员工和校长的共同任务,所以我提供了一个默认扩展,它提供了 doesWork() 的实现并说上课。

现在让我们编写一个 Staff 结构体,它将向 staffProtocol 确认,

struct Staff : staffProtocol {
        var classHour: Int = 0
        var numberOfClass: Int? = 0
    }

现在如果我创建一个职员对象作为

var staff = Staff()
staff.doesWork()

一切正常,现在让我们创建一个 Principal 结构,它也将扩展 staffProtocol,

struct Principal : staffProtocol {
    var classHour: Int = 0
    var numberOfClass: Int? = 0

    mutating func doesWork() {
           print("Also controls other staff")
    }
}

现在除了教学,他还控制其他员工,所以如果我覆盖 doesWork() 并编写 “Also controls other staff”。现在将永远不会调用默认扩展中的代码。

现在为了同时提供教学能力和控制能力,我有两个方法,

  1. 我可以创建另一个协议(protocol)来模拟控制能力并制作主要结构来扩展它

  2. staffProtocol 的默认扩展中的整个代码复制到主体结构的 doesWork 实现中,并添加一行内容为 Also controls other staff。

问题:

解决方案 1 的问题。我们在继承中遇到了类似的问题,当需要实现属于两个不同父类的功能时,由于不允许多重继承,我们曾经将功能创建为组件并将组件作为属性添加到父类中,所以我们可以在不必实现多重继承的情况下实现多重功能(无论如何这是不允许的)。但是苹果说它的代码太多而且绝对不是必需的。

即使使用面向协议(protocol)的编程,如果我必须将每个功能实现为一个协议(protocol),我不会遇到同样的问题吗?我不是将功能创建为组件,而是将其创建为协议(protocol)吗?该协议(protocol)如何在这里增加好处?

解决方案 2 的问题。因为我无法调用协议(protocol)的默认扩展并最终再次在特定于结构的实现中编写整个代码,所以我不是最终遇到了代码重复问题,这是继承首先尝试解决的常见问题吗?

问题

我正在尝试寻找解决方案的问题不是我该如何解决?每个问题都有 100 种解决方法,我想问的是,

  1. 协议(protocol)编程真的可以替代面向对象编程吗?

  2. 协议(protocol)真的可以替代继承吗?如果是,费用是多少?简单地编写 super.doesWork() 是清楚的还是为每个功能编写单独的协议(protocol)?

我可能完全误解了面向协议(protocol)编程的概念,请帮助我理解。

最佳答案

(虽然参加派对已经很晚了。我是在对 POP 有了一些初级知识后才看到这个帖子的)

假设您要编写一些鸟类类。喜欢:

  • 飞扬的小鸟
  • swift
  • 鹳鸟
  • 企鹅鸟
  • 鸵鸟
  • 鹰鸟

有些可以飞,有些不能。在 OOP 中,您有多种设计选项。最常见的是:

  1. 您设计了一个基类Fly,然后通过子类化它您设计了Bird,然后您使用这个Bird 作为基类问题中所有鸟类类的类。覆盖每种鸟类的飞行/不飞行行为。

  2. 或者,您可以有一个基类 Fly,将其子类化为 FlyingBird。然后你有另一个基类 NotFlyingBird。之后,您可以根据需要对这两个类进行子类化。

上述方法有效。但是对于案例 1

,您会看到:

Every time you create a new bird, you are also inheriting some capabilities that you don't need maybe.

情况 2 中:

You create two separate base class of your need! What if you need to write something common for FlyingBird and NotFlyingBird? You will probably end up changing your mind to use the approach 1 here.

最后,每次您以后改变主意时,您最终都会从不同的基类继承。或者只是将所有行为添加到一个神一般的


现在看看,如何使用 POP 方法设计它。

protocol Flyable { ... }
protocol Bird { ... }

struct Flappy: Bird, Flyable { ... } //it's a bird & can fly
struct SwiftBird: Bird, Flyable { ... } //it's a bird & can fly
struct Stork: Bird, Flyable { ... } //it's a bird & can fly
struct Penguin: Bird { ... } //it's a bird but can't fly
struct Ostrich: Bird { ... } //it's a bird but can't fly
struct Eagle: Bird, Flyable { ... } //it's a bird & can fly

看! POP 是如何真正发光的? 所以,幸好你没有采用继承方法,毕竟让所有的鸟都能飞!

使用面向协议(protocol)的编程,您不会神奇地从父类(super class) 继承所有内容。你正在强制提供他们自己的。通过这种方法,您可以添加行为。因此,您可以减轻肩上的负担。

If you need anything very new, you just add to them and not enforcing every other one to have that very new thing without their actual consent.

Introducing Protocol-Oriented Programming in Swift 3 RayWenderlich 的文章甚至可能会让您更加轻松。

你甚至可以看看 this answer来自不同的线程。


让我们简短地回答您的后续问题:

  1. 协议(protocol)编程真的可以替代 OOP 吗? -> 并非总是如此。但它有它的光芒。
  2. 协议(protocol)真的可以替代继承吗? -> 同样,不,但是!!如果您是从头开始设计,那么尝试这个想法是值得的。

关于ios - 面向协议(protocol)的编程不会带来继承主要解决的代码重复问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39409877/

相关文章:

ios - 如何在alert.addTextfield中放置$硬币掩码?

php - 错误域=NSCocoaErrorDomain 代码=3840 JSONObject

ios - 如何循环遍历 Firebase 数据

java - 什么时候使用 super()?

javascript - 在javascript中调用祖父函数

java - Appium - 弹出警报消息没有被关闭

ios - "finger"事件何时作为手势发送到 UIGestureRecognizer vs touchesBegan/touchesMoved/touchesEnded 到 UIView

iOS( swift ): Protocol for UIViewController that adds a new object

iphone - itms-services//action=download-manifest url 作为本地文件

java - JAX-RS 响应的效用与组合与继承