我倾向于只把必要的东西(存储属性、初始值设定项)放入我的类定义中,并将其他所有东西放入它们自己的extension
中,有点像每个逻辑块extension
,我也会将其分组为// MARK:
.
例如,对于一个UIView子类,我最终会得到一个与布局相关的扩展,一个用于订阅和处理事件等.在这些扩展中,我不可避免地要覆盖一些UIKit方法,例如layoutSubviews
.直到今天,我才注意到这种方法有任何问题.
以这个类层次 struct 为例:
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
关键字添加到定义或重写中,似乎确实会"从类层次 struct 的那个点向下"提供所需的行为...
让我们把我们的例子换成一个不那么复杂的例子,到底是什么让我发布了这个问题:
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的布局子视图动态化.
将这两个重写移到它们的类声明中,我们再次得到A A A
,只有A或B仍然得到A B A
.dynamic
再次解决了我的问题.
理论上,我可以在我做的所有override
项中加dynamic
项,但我觉得我在做别的错事.
像我这样用extension
来分组代码真的不对吗?