在某些情况下,扩展中的重写方法签名似乎会产生不可预测的结果.以下示例演示了具有类似模式的两种不同结果.
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()
Run Code Online (Sandbox Code Playgroud)
这打印:
dothing super class
viewdidload subclass
viewdidload superclass
Run Code Online (Sandbox Code Playgroud)
你可以看到这个跳过B的的实现doThing时,它铸造成A,但包括两个实现viewDidLoad时铸成UIViewController.这是预期的行为吗?如果是这样,原因是什么?
ENV:Xcode 7.3,游乐场
mat*_*att 13
令人惊讶的是,编译器允许扩展中的覆盖.这不编译:
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()
}
}
Run Code Online (Sandbox Code Playgroud)
在您的示例中,似乎编译器为您提供了一个传递,因为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()
}
}
Run Code Online (Sandbox Code Playgroud)
我的猜测是,你被允许做这个覆盖的事实本身可能是一个错误.该文件说:
扩展可以为类型添加新功能,但它们不能覆盖现有功能.
并且覆盖无法列为扩展可以做的事情之一.所以,看起来这应该不是编译.但是,正如我之前所说的那样,也许这是有意与Objective-C兼容的.无论哪种方式,我们正在探索一个边缘情况,你已经很好地引出了它的边缘.
特别是,前面的代码仍然不会导致动态调度变得可操作.这就是为什么你要doThing像dynamic@jtbandes所说的那样声明为或者把它放在实际的类而不是扩展中 - 如果你想要多态运行的话.因此,这可以按照您的预期方式工作:
class A : NSObject {
dynamic func doThing() {
print("dothing super class")
}
}
class B: A {
}
extension B {
override func doThing() {
print("dothing sub class")
super.doThing()
}
}
Run Code Online (Sandbox Code Playgroud)
这样做:
class A : NSObject {
func doThing() {
print("dothing super class")
}
}
class B: A {
override func doThing() {
print("dothing sub class")
super.doThing()
}
}
Run Code Online (Sandbox Code Playgroud)
我的结论是:非常好的例子; 将其作为可能的错误提交给Apple; 并且不要那样做.在课堂上重写,而不是在扩展中.
| 归档时间: |
|
| 查看次数: |
908 次 |
| 最近记录: |