ios – Swift在子类扩展中调度到覆盖的方法

ios – Swift在子类扩展中调度到覆盖的方法,第1张

概述扩展中的重写方法签名似乎在某些情况下产生不可预知的结果.以下示例演示了两种具有相似模式的不同结果. class A: UIViewController { func doThing() { print("dothing super class") } override func viewDidLoad() { print("viewdidl 扩展中的重写方法签名似乎在某些情况下产生不可预知的结果.以下示例演示了两种具有相似模式的不同结果.
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 classvIEwdIDload subclassvIEwdIDload 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()    }}

在你的例子中,似乎编译器给你一个pass,因为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()    }}

我的猜测是,你被允许这样做的事实本身就可能是一个BUG. docs说:

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

超越是没有被列为扩展可以做的事情之一.所以似乎这不应该编译.但是,如我之前所说,也许这是有意识的兼容Objective-C.无论哪种方式,我们正在探索一个边缘的情况,你非常好地引出了它的边缘.

特别地,上述代码仍然不会导致动态调度成为可 *** 作的.这就是为什么你必须声明doThing是动态的,如@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()    }}

这样做也是如此:

class A : NSObject {    func doThing() {        print("dothing super class")    }}class B: A {    overrIDe func doThing() {        print("dothing sub class")        super.doThing()    }}

我的结论是:非常好的例子将其提交给苹果作为可能的错误;不要这样做在课堂上超越,而不是延伸.

总结

以上是内存溢出为你收集整理的ios – Swift在子类扩展中调度到覆盖的方法全部内容,希望文章能够帮你解决ios – Swift在子类扩展中调度到覆盖的方法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1110199.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存