[英]Swift dispatch to overridden methods in subclass extensions
在某些情況下,擴展中的重寫方法簽名似乎會產生不可預測的結果。 以下示例演示了具有類似模式的兩種不同結果。
class A: UIViewController {
func doThing() {
print("dothing super class")
}
override func viewDidLoad() {
print("viewdidload superclass")
super.viewDidLoad()
}
}
class B: A { }
extension B {
override func doThing() {
print("dothing sub class")
super.doThing()
}
override func viewDidLoad() {
print("viewdidload subclass")
super.viewDidLoad()
}
}
let a: A = B()
a.doThing()
let vc: UIViewController = B()
vc.viewDidLoad()
這打印:
dothing super class
viewdidload subclass
viewdidload superclass
你可以看到它在轉換為A
時跳過了B
的doThing
實現,但是在轉換為UIViewController
時包含了viewDidLoad
兩種實現。 這是預期的行為嗎? 如果是這樣,原因是什么?
ENV:Xcode 7.3,游樂場
令人驚訝的是,編譯器允許擴展中的覆蓋。 這不編譯:
class A {
func doThing() {
print("dothing super class")
}
}
class B: A {
}
extension B {
override func doThing() { // error: declarations in extensions cannot override yet
print("dothing sub class")
super.doThing()
}
}
在您的示例中,似乎編譯器為您提供了一個傳遞,因為A派生自NSObject - 可能是為了允許此類與Objective-C進行交互。 這確實編譯:
class A : NSObject {
func doThing() {
print("dothing super class")
}
}
class B: A {
}
extension B {
override func doThing() {
print("dothing sub class")
super.doThing()
}
}
我的猜測是,你被允許做這個覆蓋的事實本身可能是一個錯誤。 文檔說:
擴展可以為類型添加新功能,但它們不能覆蓋現有功能。
並且覆蓋無法列為擴展可以做的事情之一。 所以它看起來像這不應該編譯。 但是,正如我之前所說的那樣,也許這是有意與Objective-C兼容的。 無論哪種方式,我們正在探索一個邊緣情況,你已經很好地引出了它的邊緣。
特別是,前面的代碼仍然不會導致動態調度變得可操作。 這就是為什么你要么必須像doThing
那樣將doThing
聲明為dynamic
,要么將它放在實際的類而不是擴展中 - 如果你想要多態運行的話。 因此,這可以按照您的預期方式工作:
class A : NSObject {
dynamic func doThing() {
print("dothing super class")
}
}
class B: A {
}
extension B {
override func doThing() {
print("dothing sub class")
super.doThing()
}
}
這樣做:
class A : NSObject {
func doThing() {
print("dothing super class")
}
}
class B: A {
override func doThing() {
print("dothing sub class")
super.doThing()
}
}
我的結論是:非常好的例子; 將其作為可能的錯誤提交給Apple; 並且不要那樣做。 在課堂上重寫,而不是在擴展中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.