【发布时间】:2016-11-07 20:56:06
【问题描述】:
我倾向于只将必需品(存储的属性、初始化程序)放入我的类定义中,并将其他所有内容移入它们自己的extension,有点像每个逻辑块的extension,我将与// MARK: 分组为好吧。
例如,对于 UIView 子类,我最终会得到一个与布局相关的东西的扩展,一个用于订阅和处理事件等等。在这些扩展中,我不可避免地不得不重写一些 UIKit 方法,例如layoutSubviews。直到今天,我才注意到这种方法有任何问题。
以这个类层次结构为例:
public class C: NSObject {
public func method() { print("C") }
}
public class B: C {
}
extension B {
override public func method() { print("B") }
}
public class A: B {
}
extension A {
override public func method() { print("A") }
}
(A() as A).method()
(A() as B).method()
(A() as C).method()
输出为A B C。这对我来说意义不大。我读到了关于静态分派的协议扩展,但这不是协议。这是一个常规类,我希望方法调用在运行时动态分派。显然,对C 的调用至少应该动态调度并产生C?
如果我从NSObject 删除继承并将C 设为根类,编译器会抱怨说declarations in extensions cannot override yet,我已经读过。但是将NSObject 作为根类会如何改变事情呢?
将两个覆盖都移到它们的类声明中,如预期的那样产生A A A,只移动B产生A B B,只移动A产生C B C,最后一个完全没有意义我:即使是静态输入到A 的那个也不再产生A-输出!
将dynamic 关键字添加到定义或覆盖似乎确实给了我所需的行为“从类层次结构中的那个点向下”...
让我们把我们的例子改成稍微不那么结构的东西,实际上是什么让我发布了这个问题:
public class B: UIView {
}
extension B {
override public func layoutSubviews() { print("B") }
}
public class A: B {
}
extension A {
override public func layoutSubviews() { print("A") }
}
(A() as A).layoutSubviews()
(A() as B).layoutSubviews()
(A() as UIView).layoutSubviews()
我们现在得到A B A。在这里,我无法以任何方式使 UIView 的 layoutSubviews 动态化。
将两个覆盖都移到它们的类声明中再次得到A A A,只有A或只有B仍然得到A B A。 dynamic 再次解决了我的问题。
理论上我可以将dynamic 添加到我曾经做过的所有overrides 中,但我觉得我在这里做错了什么。
像我这样使用extensions 对代码进行分组真的错了吗?
【问题讨论】:
-
以这种方式使用扩展是 Swift 的惯例。甚至 Apple 在标准库中也这样做。
-
@AMomchilov 你链接的文件谈到了协议,我错过了什么吗?
-
我怀疑这两种机制都适用
-
似乎重复了Swift dispatch to overridden methods in subclass extensions。马特的回答是这是一个错误(他引用了文档来支持这一点)。
标签: swift swift2 swift-extensions