在Swift中,为什么子类方法不能覆盖超类中协议扩展提供的方法

时间:2015-10-07 14:06:29

标签: swift protocols swift2 xcode7

我知道这个问题的标题令人困惑,但下面的例子解释了奇怪的行为:

protocol Protocol {
    func method() -> String
}

extension Protocol {
    func method() -> String {
        return "From Base"
    }
}

class SuperClass: Protocol {
}

class SubClass: SuperClass {
    func method() -> String {
        return "From Class2"
    }
}

let c1: Protocol = SuperClass()
c1.method() // "From Base"
let c2: Protocol = SubClass()
c2.method() // "From Base"

c1.method()c2.method()如何归来?为什么SubClass中的method()不起作用?

有趣的是,如果没有声明c2的类型,这将起作用:

let c2  = SubClass()
c2.method() // "From Class2"

3 个答案:

答案 0 :(得分:1)

问题是c1c2的类型为Protocol,因为您已经以这种方式明确定义了它们的类型(请记住:协议是完全成熟的类型)。这意味着,在调用method()时,Swift会调用Protocol.method

如果您定义如下内容:

let c3 = SuperClass()

... c3的类型为SuperClass。由于SuperClass没有更具体的method()声明,因此在调用Protocol.method()时仍会使用c3.method()

如果您定义如下内容:

let c4 = SubClass()

... c4的类型为SubClass。由于SubClass确实有更具体的method()声明,因此在调用SubClass.method()时会使用c4.method()

你也可以c2来调用SubClass.method(),将它下载到`SubClass:

(c2 as! SubClass).method() // returns "From Class2"

这是SwiftStub的演示。

答案 1 :(得分:0)

我不太确定底层机制,但它必须与协议不一定允许继承这一事实有关。

解决此问题的一种方法是将方法添加到SuperClass

import Foundation
protocol Protocol: class {
    func method() -> String
}

extension Protocol {
    func method() -> String {
        return "From Base"
    }
}

class SuperClass: Protocol {
    func method() -> String {
        return "From Super"
        }
}

class SubClass: SuperClass {
    override func method() -> String {
        return "From Class2"
    }
}

let c1: Protocol = SuperClass()
c1.method() // "From Super"
let c2: Protocol = SubClass()
c2.method() // "From Class2"

答案 2 :(得分:0)

基本上是的,如果有一个符合协议的超类但没有为它提供实现,那么协议扩展的实现将在子类中可用,即使子库已实现(但是它们必须被转换为超类或协议的类型。

但是,如果超类具有协议方法的实现,那么协议的实现将无法从超类或其子类中获得。