有点 Nerd 的问题。我不清楚究竟是什么让这段代码起作用:
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
关键字,代码将不会编译 - 这是预期的行为,因为扩展中的方法使用静态方法分派(dispatch) -> 不能被覆盖。
但是为什么添加 @objc
可以让它工作呢?根据文档和大多数文章,@objc
所做的只是让 Objective-c 运行时可见。要更改方法分派(dispatch)类型,有一个特殊的关键字 - dynamic
。不过这里好像没必要!
帮我弄清楚,为什么添加 @objc
(并省略 dynamic
)使这些事情成为可能。
最佳答案
as the name already says, are supposed to extend/add/include methods to an existing implementation, making them one of the most beautiful things about Objective-C, and now Swift, since you can add code to a class or framework you do not own. Therefore, it makes sense that you’re not supposed to “replace” code in extensions, conceptually speaking.
这就是编译器在您尝试这样做时会报错的原因。
另请查看此 answer .
然而这似乎也是一个支持问题,因为 swift 编译器只是抛出这个错误:
overriding non-@objc declarations from extensions is not supported.
据苹果称,
Extensions can add new functionality to a type, but they cannot override existing functionality.
但事实并非如此,因为我们是从扩展中覆盖而不是相反,
这将我们带回到 extension
的声明。
Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you do not have access to the original source code (known as retroactive modeling). Extensions are similar to categories in Objective-C. (Unlike Objective-C categories, Swift extensions do not have names.) Here.
回到遗留主题 swift 编译器 vs Objc 编译器,
动态调度与静态调度。
苹果没有官方文档说明为什么 swift 编译器不支持它,或者他们是否有任何 future 的计划来解决这个问题或将其视为一个问题。
However, there’s no such thing as Swift dynamic dispatch; we only have the Objective-C runtime’s dynamic dispatch. That means you can’t have just dynamic and you must write @objc dynamic. So this is effectively the same situation as before, just made explicit.
这是一个很棒的 article深入探讨这个话题。
关于swift - 用 '@objc' 属性覆盖扩展方法背后的机制是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54852486/