协议之间的实现冲突

BPC*_*orp 10 oop inheritance implementation protocols swift

我偶然发现了一个问题,我无法弄清楚如何解决它.

假设我们有一个基类(可能来自FrameworkA),其属性名为subject:

public class MyClass {
    public var subject: String
}
Run Code Online (Sandbox Code Playgroud)

我们有一个协议(可能来自FrameworkB),另一个属性但具有相同的名称:

public protocol MyProtocol {
    var subject: String { get }
}
Run Code Online (Sandbox Code Playgroud)

这两个属性代表完全不同的东西.

如何创建一个继承MyClass和实现的类MyProtocol?我该如何使用这些属性?

public class SecondClass: MyClass, MyProtocol {
    var MyProcotol.name: String { // <==== Obviously not allowed
        return "something"
    }
    var MyClass.name: String { // <==== Obviously not allowed
        return "something else"
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为C#允许这样的声明,但我不是100%肯定...

Luc*_*tti 1

好吧,让我们暂时从使用这些类的代码的角度来看一下问题,并忽略它们是如何实现的。

事实1

如果SecondClass : SecondClass 扩展,MyClass那么我希望能够写:

secondClass.subject
Run Code Online (Sandbox Code Playgroud)

事实2

如果secondClass符合那么MyProtocol我希望能够写

secondClass.subject
Run Code Online (Sandbox Code Playgroud)

如果我们创建一种不同的secondClass公开方式MyClass.subject,那么MyProtocol.subject我们就打破了面向对象的范式。

实际上

  1. 当你扩展一个类时,你隐式继承了所有非私有属性和方法,你不能(这是一件好事)重命名它们。
  2. 当您遵守协议时,您将完全按照协议中的描述公开所有非可选声明的属性和方法

如果SecondClass像伪代码中那样重命名这两个属性,我们将无法编写这样的内容。

let list : [MyClass] = [MyClass(), SecondClass()]

for elm in list {
    println(elm.subject)
}
Run Code Online (Sandbox Code Playgroud)

可能的(部分)解决方案

您应该避免使用is-a方法,而使用has-a

class SecondClass {
    let myClass : MyClass
    let somethingElse : MyProtocol

    init(myClass : MyClass, somethingElse:MyProtocol) {
        self.myClass = myClass
        self.somethingElse = somethingElse
    }

    var myClassSubject : String { get { return myClass.subject } }
    var myProtocolSubject : String { get { return somethingElse.subject } }
}
Run Code Online (Sandbox Code Playgroud)

现在自从

  1. SecondClass 不是一个MyClass并且
  2. SecondClass 不是一个MyProtocol

它没有subject消除任何混淆风险的特性。

希望这可以帮助。

  • 这里的问题是我们正在处理与 OOP 相关的概念约束。我真的不知道如何改变语言本身来管理这种情况。 (2认同)