书呆子问题的种类。对我来说还不清楚,究竟是什么使该代码起作用:
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
如果我省略扩展名中的@objc
关键字,则代码将无法编译-这是预期行为,因为扩展名中的方法使用静态方法分派->无法覆盖。
但是为什么要添加@objc
使其起作用呢?根据文档和大多数文章的介绍,@objc
的全部工作是使事物对Objective-c运行时可见。要更改方法分派类型,有一个特殊的关键字-dynamic
。但似乎这里没有必要!
帮我弄清楚,为什么添加@objc
(并省略dynamic
)使这种事情成为可能。
答案 0 :(得分:3)
顾名思义,应该是扩展/添加/包含方法 到现有的实现中,使它们成为最漂亮的之一 关于Objective-C,现在是Swift,因为您可以将代码添加到 您不拥有的类或框架。因此,有道理 从概念上讲,您不应该在扩展程序中“替换”代码 说话。
这就是为什么编译器在尝试这样做时会抱怨的原因。
也请查看此answer。
但是这似乎也是一个支持问题,因为快速编译器只会抛出此错误:
不支持从扩展名覆盖非@objc声明。
根据苹果公司
扩展可以为类型添加新功能,但不能 覆盖现有功能。
事实并非如此,因为我们从扩展名中覆盖,反之亦然,
这使我们回到了extension
的声明。
扩展将新功能添加到现有的类,结构,枚举或协议类型。这包括扩展您无法访问原始源代码的类型的能力(称为追溯建模)。扩展与Objective-C中的类别相似。 (与Objective-C类别不同,Swift扩展名没有名称。)Here。
回到旧主题 swift编译器与Objc编译器
动态分配与静态分配。
而且,苹果公司也没有官方文件说明为什么Swift编译器不支持此功能,或者他们是否有未来的计划来解决此问题或将其视为根本问题。
However,没有诸如Swift动态调度之类的东西;我们只有 Objective-C运行时的动态分配。这意味着你不能 只是动态的,您必须编写@objc动态的。所以这是有效的 与以前相同的情况,只是明确了。
下面是一个很棒的article,深入讨论了这个话题。