覆盖符合协议的var,其中var符合被覆盖的var协议的子节点

时间:2015-03-18 12:08:06

标签: ios swift

这是我的继承结构

协议

protocol BaseProtocol {
}

protocol ChildProtocol: BaseProtocol {
}

class BaseClass: NSObject {

    var myVar: BaseProtocol!
}

class ChildClass: BaseClass {

    override var myVar: ChildProtocol!
}

我收到编译错误:

Property 'myVar' with type 'ChildProtocol!' cannot override a property with type 'BaseProtocol!'

实现这一目标的最佳方法是什么?

更新

我更新了尝试使用泛型实现解决方案的问题,但它不起作用:(这是我的代码(现在是真正的代码,没有示例)

协议

protocol TPLPileInteractorOutput {
}

protocol TPLAddInteractorOutput: TPLPileInteractorOutput {  

    func errorReceived(error: String)
}

class TPLPileInteractor<T: TPLPileInteractorOutput>: NSObject, TPLPileInteractorInput {

    var output: T!
}

我的孩子们

class TPLAddInteractor<T: TPLAddInteractorOutput>: TPLPileInteractor<TPLPileInteractorOutput>, TPLAddInteractorInput {
}

好吧,在TPLAddInteractor我无法访问self.output内部,它会抛出编译错误,例如

'TPLPileInteractorOutput' does not have a member named 'errorReceived'

除此之外,当我创建TPLAddInteractor

的实例时
let addInteractor: TPLAddInteractor<TPLAddInteractorOutput> = TPLAddInteractor()

我收到了其他错误

Generic parameter 'T' cannot be bound to non-@objc protocol type 'TPLAddInteractorOutput'

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

我认为你不能用protocols

来做到这一点

我将解决您遇到的问题的方法是使用generics。这意味着您基本上拥有这样的类(更新为工作示例)。

<强>协议

protocol BaseProtocol {
    func didSomething()
}
protocol ChildProtocol: BaseProtocol {
    func didSomethingElse()
}

<强>类

class BaseClass<T: BaseProtocol> {
    var myProtocol: T?

    func doCallBack() {
        myProtocol?.didSomething()
    }
}
class ChildClass<T: ChildProtocol> : BaseClass<T> {
    override func doCallBack() {
        super.doCallBack()
        myProtocol?.didSomethingElse()
    }
}

实施/使用示例

class DoesSomethingClass : ChildProtocol {
    func doSomething() {
        var s = ChildClass<DoesSomethingClass>()
        s.myProtocol = self
        s.doCallBack()
    }

    func didSomething() {
        println("doSomething()")
    }
    func didSomethingElse() {
        println("doSomethingElse()")
    }
}

let foo = DoesSomethingClass()
foo.doSomething()

请记住,您需要一个实际实现协议的类,以及您实际定义为BaseClass / ChildClass的泛型类的THAT类。由于代码期望类型是符合协议的类型。

答案 1 :(得分:1)

@tskulbru是正确的:它无法完成,这与您的协议无关。考虑下面的示例,其中失败......这次是Cannot override with a stored property 'myVar'

class Foo {
}

class Goo: Foo {
}

class BaseClass: NSObject {
   var myVar: Foo!
}

class ChildClass: BaseClass {
   override var myVar: Foo!
}

要理解原因,让我们重新检查docs

  

覆盖属性

     

您可以覆盖要提供的继承实例或类属性   您自己的该属性的自定义getter和setter,或者要添加   属性观察者使覆盖属性能够观察何时   基础财产价值变动。

暗示如果要覆盖属性,必须编写自己的getter / setter,否则必须添加属性观察者。不允许简单地将一种变量类型替换为另一种变量类型。

现在有一些猖獗的猜测:为什么会这样?好吧,一方面考虑Swift 打算为速度进行优化。必须进行运行时类型检查才能确定您的var实际上是Foo还是Bar,这会减慢速度。然后考虑语言设计者可能更喜欢组合而不是继承。如果这两个都是真的,那么你不能覆盖属性的类型就不足为奇了。

所有这一切,如果您需要获得相同的行为,@ tskulbru的解决方案看起来非常优雅,假设您可以进行编译。 :)

答案 2 :(得分:0)

您可以通过两种方式使用代码,具体取决于您希望使用代码实现的目标(您没有告诉我们)。

简单的情况:您只是希望能够将一个确认ChildProtocol的对象分配给myVar。 解决方案:不要覆盖myVar。只需在ChildClass中使用它。你可以通过设计Swift语言来做到这一点。它是面向对象语言的基础之一。

第二种情况:您不仅要启用分配ChildProtocol的实例,还要禁用能够分配BaseProtocol的实例。 如果您想这样做,请使用答案部分提供的Generics解决方案。

如果您不确定,这个简单的案例对您来说是正确的。

格尔德