【问题标题】:Swift: Why is the default protocol implementation used when an override is in place?Swift:为什么在覆盖到位时使用默认协议实现?
【发布时间】:2020-01-13 02:56:32
【问题描述】:

我在提取示例的原始代码中的意图是让协议为许多抽象类提供一些默认实现,并根据需要在这些类下面的层次结构中进行覆盖。然而事情并没有按计划进行。

这是基本代码(取自游乐场,我将原始代码简化为问题的本质):

// protocol and default impls.

protocol MyProtocol {
    func hello()
}

extension MyProtocol {
    func hello() { print("hello from default in protocol extension") }
}

// Class hierarchy

class AbstractParent: MyProtocol {}

class Child: AbstractParent {
    func hello() { print("hello from child") }
}

(Child() as MyProtocol).hello()
Child().hello()

运行这个我希望看到:

hello from child
hello from child

但是却得到了:

hello from default in protocol extension
hello from child

这对我来说很有意义,因为第一次调用是从 Child 转换为 MyProtocol 进行的,即使该函数存在于 Child 中,它也会调用协议函数,因为在编译时它只看到MYProtocol.

不过……

如果我将抽象父对象设置为包含这样的默认实现:

// protocol and default impls.

protocol MyProtocol {
    func hello()
}

extension MyProtocol {
    func hello() { print("hello from default in protocol extension") }
}

// Class hierarchy

class AbstractParent: MyProtocol {
    func hello() { print("hello from abstract parent") }
}

class Child: AbstractParent {
    override func hello() { print("hello from child") }
}

(Child() as MyProtocol).hello()
Child().hello()

我现在得到了预期的行为:

hello from child
hello from child

现在,尽管我们仍在转换为 MyProtocol,但它在 Child 中看到了实现。

谁能解释为什么向抽象父类添加一个实现会使这项工作有效?

【问题讨论】:

    标签: swift protocols


    【解决方案1】:

    与一位比我更了解 Swift 的同事交谈,他说这是 Swift 中一个颇具争议的已知事物的一个例子。

    我会试着在这里概述一下,以便其他人也能理解。

    据我了解 - 当 Swift 解析函数时,它从实现它的最常见的祖先开始。因此,在我执行错误的第一个示例中,它以AbstractParent 开头并在协议中找到hello() 函数。因为AbstractParent 没有该函数的实现并且Child 中的hello() 函数没有用override 声明,所以Swift 编译器认为它是一个不同的函数,即使它看起来像一个覆盖。因此它没有调用它。

    在第二个例子中,我们在AbstractParent 中有一个hello() 函数,在Child 中有一个真正的覆盖。所以 Swift 看到了抽象的实现和覆盖,并调用了正确的。

    这个问题实际上是 Swift 在解决时如何看待的事情之一,即使我们作为“普通”开发人员认为实现中的任何声明的函数都会覆盖协议中的任何内容,但实际上并非总是如此。

    正确地,唯一已知的解决方案是像我一样将默认实现添加到抽象类中。

    对于我的项目,我将考虑我的实现和层次结构,看看是否有更好的解决方案,但目前看来还没有。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-30
      • 2017-08-13
      • 1970-01-01
      • 2023-03-19
      • 2017-12-23
      • 2015-09-22
      • 1970-01-01
      相关资源
      最近更新 更多