gpt4 book ai didi

ios - Swift 分派(dispatch)到子类扩展中的重写方法

转载 作者:IT王子 更新时间:2023-10-29 05:21:31 27 4
gpt4 key购买 nike

在某些情况下,覆盖扩展中的方法签名似乎会产生不可预知的结果。以下示例演示了具有相似模式的两个不同结果。

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

B 转换为 A 时,您可以看到它跳过了 doThing 的实现,但是包括 的两个实现>viewDidLoad 当转换为 UIViewController 时。这是预期的行为吗?如果是这样,这是什么原因?

环境:Xcode 7.3, Playground

最佳答案

令人惊讶的是,编译器允许在扩展中覆盖。这编译:

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()
}
}

我的猜测是,您被允许执行此覆盖这一事实本身可能是一个错误。 docs说:

Extensions can add new functionality to a type, but they cannot override existing functionality.

并且覆盖没有被列为扩展可以做的事情之一。所以看起来这应该编译。然而,正如我之前所说,也许这是为了与 Objective-C 兼容而故意允许的。无论哪种方式,我们都在探索一种边缘情况,您已经很好地引出了它的边缘性。

特别是,前面的代码仍然没有使动态调度变得可操作。这就是为什么您必须按照@jtbandes 的建议将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;并且不要那样做。在类中进行覆盖,而不是在扩展中。

关于ios - Swift 分派(dispatch)到子类扩展中的重写方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37492897/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com