扩展方法覆盖'@objc'属性背后的机制是什么?

sur*_*der 6 swift

一种书呆子的问题.我不清楚,这段代码的确切作用是什么:

class Shape { }

extension Shape {
    @objc func redraw() {
        print("from ext")
    }
}

class Circle: Shape { }

class Line: Shape {
    override func redraw() { // Compiler error: Declarations from extensions cannot be overridden yet
        print("from subclass")
    }
}

let line = Line()
let shape:Shape = line
let circle = Circle()

line.redraw() //from subclass
circle.redraw() //from ext
shape.redraw() //from subclass
Run Code Online (Sandbox Code Playgroud)

如果我@objc在扩展中省略了关键字,代码将无法编译 - 这是预期的行为,因为扩展中的方法使用静态方法dispatch - >无法覆盖.但为什么添加@objc使它工作?根据文档和大多数文章,所有正在@objc做的是使Objective-c运行时可见.要更改方法分派类型,有一个特殊的关键字 - dynamic.但似乎这里没有必要!

帮助我弄清楚,为什么添加@objc(和省略dynamic)使这些事情成为可能.

Moh*_*d S 3

扩展,

\n\n
\n

顾名思义,应该将方法扩展/添加/包含到现有的实现中,使它们成为 Objective-C 最美丽的东西之一,现在是 Swift,因为您可以将代码添加到您不拥有的类或框架。因此,从概念上来说,\n 你\xe2\x80\x99 不应该\xe2\x80\x9c 替换\xe2\x80\x9d 代码是有道理的。

\n
\n\n

这就是为什么当你尝试这样做时编译器会抱怨的原因。

\n\n

另请查看此答案。

\n\n

然而这似乎也是一个支持问题,因为 swift 编译器只是抛出这个错误:

\n\n
\n

不支持覆盖扩展中的非 @objc 声明。

\n
\n\n

据苹果公司称,

\n\n
\n

扩展可以向类型添加新功能,但不能覆盖现有功能。

\n
\n\n

但事实并非如此,因为我们是从扩展覆盖的,反之亦然,\n这让我们回到了 的声明extension。

\n\n
\n

扩展向现有的类、结构、枚举或协议类型添加新功能。这包括扩展您无权访问原始源代码的类型的能力(称为追溯建模)。扩展类似于 Objective-C 中的类别。(与 Objective-C 类别不同,Swift 扩展没有名称。)这里.

\n
\n\n

回到遗留主题swift 编译器与 Objc 编译器,

\n\n

动态调度与静态调度。

\n\n

苹果没有官方文档说明为什么 swift 编译器不支持此功能,或者他们是否有任何未来计划来解决此问题或将其视为一个问题。

\n\n
\n

然而,\xe2\x80\x99s 没有 Swift 动态调度这样的东西;我们只有 Objective-C 运行时 xe2x80x99s 动态调度。这意味着您不能\xe2\x80\x99\n 只是动态的,并且必须编写@objc 动态。因此,这实际上与之前的情况相同,只是明确了而已。

\n
\n\n

这是一篇很棒的文章深入讨论了这个话题。

\n