面向协议的编程是否带来了与继承主要解决的代码重复相同的旧问题? [英] Doesn't Protocol Oriented programming bring the same old issue of code duplication which inheritance primarily solved?

查看:109
本文介绍了面向协议的编程是否带来了与继承主要解决的代码重复相同的旧问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

概述

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

I was trying to get my head around Swift's Protocol Oriented Programming paradigm. As per Apple's WWDC 2015 video https://developer.apple.com/videos/play/wwdc2015/408/ Protocols can achieve everything that inheritance can and also solves the fundamental issue with inheritance.

尽管Protocols通过捕获每个继承来解决多重继承问题作为协议的功能(功能)和允许类/结构确认多个协议,我相信协议永远不能替代继承,原因如下。

Though Protocols solves the problem of multiple inheritance by capturing each capability (functionality) as protocol and allowing a class/struct to confirm multiple protocols, I believe Protocols can never replace inheritance for the following reason.

让我们假设我正在实施College /学校自动化软件,有两个实体,工作人员和校长,我们假设他们都上课,但是校长和课程控制工作人员。

Lets assume I am implementing College/School automation software and there are two Entities, Staff and Principal and lets assume they both take class but principal along with taking class controls the staff.

所以我创建了一个协议这将模拟正在上课的共同能力。所以让我们创建一个协议。

So I create a protocol which will model the common capability which is taking class. So let's create a 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")
    }
}

由于Take class是工作人员和校长的共同任务所以我提供了一个默认扩展,它为 doesWork()提供了一个实现,并说。

As Taking class is a common task for both staff and principal so I provided a default extension which provides a implementation for doesWork() and says takes class.

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

Now let's write a Staff struct which will confirm to staffProtocol,

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

现在如果我创建一个人员对象

Now if I create a staff object as

var staff = Staff()
staff.doesWork()

一切都运行得很好,现在让我们创建一个Principal结构,它也将扩展staffProtocol,

Everything works absolutely fine, now lets create a Principal struct which will also extend staffProtocol,

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

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

现在除了教学他还控制其他人员,所以如果我覆盖 didWork()并写还控制其他员工。现在永远不会调用默认扩展中的代码。

Now along with teaching he also controls other staff, so if I override doesWork() and write "Also controls other staff". Now the code in default extension will never be called.

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

Now in order to provide both teaching capability and controlling capability, I have two methods,


  1. 我可以创建另一个协议来建模控制功能并使主结构扩展它

  1. I can create another protocol which will model controlling capability and make principal struct to extend it

staffProtocol 的默认扩展名中的整个代码复制到主要结构的doWork实现中,并添加一行也控制其他人员。

Copy the whole code in default extension of staffProtocol to the principal struct's doesWork implementation and add a line which says Also controls other staff.

问题:

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

Issue with Solution 1. We faced the similar issue in Inheritance, when there was need to implement the capabilities which belonged to two different parent classes and as multiple inheritance was not allowed we used to create the capability as a component and add the component as a property to parent class so that we can achieve multiple capability without having to implement multiple inheritance (which is anyway not allowed). But apple says its too much of code and absolutely not essential.

即使是面向协议的编程,如果我必须实现每个功能,因为协议不会遇到同样的问题这个问题的角落?我不是将其创建为协议而不是创建作为组件的功能?该协议如何在此处增加收益?

Even with protocol oriented programming if I have to implement each capability as a protocol isn't am running into same nook of the problem? Rather than creating a capability as a component am I not creating it as a protocol? How is that protocol adding benefit here?

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

Issues with solution 2. Because I can't call the default extension of the protocol and end up writing the whole code in struct specific implementation again, Haven't I ended up in code duplication issue which is the common problem which inheritance tried solving in a very first place?

问题

问题我试图找到解决方案不是我怎么解决它?有100种方法可以解决每个问题,我想问的是,

Question am trying to find solution is not how can I solve it? There are 100 ways to solve each problem, all I am trying to ask is,


  1. 协议编程是否真的是Object的替代方案面向编程?

  1. Is protocol programming really an alternative to Object oriented programming?

协议真的是继承的替代品吗?如果是,费用是多少?编写简单的super.doesWork()是明确的还是为每个功能编写一个单独的协议?

Is protocol really a replacement to inheritance ? If yes at what cost? Writing simply super.doesWork() was clear or writing a separate protocol for each capability?

我可能完全被误解了面向协议编程的概念,请帮助我理解相同的内容。

I might have completely misunderstood the concept of Protocol Oriented Programming, please help me understand the same.

推荐答案

(虽然派对很晚。我遇到过关于 POP 的一些初级知识后的这个帖子

(Very late to the party though. I came across this thread after having some beginning level knowledge about the POP)

假设,你我会写一些鸟类。喜欢:

Suppose, you are going to write some bird classes. Like:


  • Flappy Bird

  • Swift Bird

  • Stork Bird

  • Penguin Bird

  • 鸵鸟鸟

  • 鹰鸟

  • Flappy Bird
  • Swift Bird
  • Stork Bird
  • Penguin Bird
  • Ostrich Bird
  • Eagle Bird

其中一些 可以 ,而某些 无法 。在OOP中,您可以设计各种选项。大多数公共场所是:

Some of them can fly and some can't. In OOP, you have various options to design. Most commons are:


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

  1. You design a base class Fly, then by subclassing it you design Bird and then you use this Bird as the base class for all the bird classes in the question. Override the flying/not flying behavior for each bird type.

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

Or, you can have a base class Fly, you subclass it for FlyingBird. And then you have another base class NotFlyingBird. After that you subclass these two classes according to your need.

上述方法有效。但你看到的是 案例1:

The above approaches work. But you see for the case 1:


每次创建一个新的鸟,你也继承了一些你不需要的功能。

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

并且在 案例中2 :

And in the case 2:


您需要创建两个独立的基类!如果您需要为 FlyingBird NotFlyingBird 编写常见内容,该怎么办?您可能最终会改变主意在这里使用方法1

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.

最后,每次都是你在以后最终从不同的基类继承时改变主意。或者只是在类神类中添加所有行为

And lastly, every time you change your mind in later time you end up inheriting from different base class. Or just adding all of the behaviors in a god-like class

现在看看,如何您可以使用 POP 方法进行设计。

Now see, how you can design this with POP approach.

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 真的闪耀? 所以,你没有采用继承方法,并且让所有的鸟类都可以飞行,这是一件好事!

See! how POP really shine? So, it’s a good thing you didn’t take the inheritance approach, and make all birds flyable after all!

使用面向协议的编程,你不会神奇地继承超类中的所有内容。您正在强制提供自己的。使用此方法,您 添加行为 。所以你可以减轻肩负的负担。

With protocol oriented programming you just don't magically inherit everything from the Super class. You are enforcing to provide their own. With this approach, you are adding behaviors. So you can keep out the burden off your shoulder.


如果你需要任何非常新的,你只需添加它们而不会强制执行其他任何没有他们的实际同意而拥有这个非常新的东西。

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.

这个

This Introducing Protocol-Oriented Programming in Swift 3 article from RayWenderlich may even lighten up you a bit more.

您甚至可以从另一个主题中查看此答案

You might even have a look at this answer from a different thread.

让我们简单回答您的尾随问题:

Let's answer your trailing questions in short:


  1. 协议编程真的可以替代OOP吗? - > 并非总是如此。但它有它的光芒。

  2. 协议真的是继承的替代品吗? - > 再次,不。但是!!如果你从头开始设计,那么值得一提这个想法。

  1. Is protocol programming really an alternative to OOP? -> Not always. But it has it's shine.
  2. Is protocol really a replacement to inheritance? -> Again, No. But!! If you are designing from the scratch it's worth it to give this idea a shot.

这篇关于面向协议的编程是否带来了与继承主要解决的代码重复相同的旧问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆