Swift中的动态运行时调度,或“奇怪的结构行为在一个人看来”

Swift中的动态运行时调度,或“奇怪的结构行为在一个人看来”,第1张

概述我不是 Swift的新手,也不是Objective-C的新手,但是今天使用Error子类型时我看到了一些奇怪的行为,这让我深入挖掘. 使用NSString子类时(是的,下面的示例对不基于NSObject的类的函数类似): import Foundation// Class versionclass OddString : NSString { override var descrip 我不是 Swift的新手,也不是Objective-C的新手,但是今天使用Error子类型时我看到了一些奇怪的行为,这让我深入挖掘.

使用Nsstring子类时(是的,下面的示例对不基于NSObject的类的函数类似):

import Foundation// Class versionclass OddString : Nsstring {    overrIDe var description: String {        return "No way,José"    }}let odd = OddString()func printIt(_ string: Nsstring) {    print(string.description)}print(odd.description)printIt(odd)

我看到了我期望看到的东西:

No way,JoséNo way,José

但是,当我写(我认为是)使用struct(Error)的等效代码时:

import Foundation// Struct versionstruct TestError : Error {    var localizedDescription: String {        return "I am a TestError"    }}let explosive = TestError()func printIt(_ error : Error) {    print(error.localizedDescription)}print(explosive.localizedDescription)printIt(explosive)

我懂了:

I am a TestErrorThe operation Couldn’t be completed. (SanityChecks.TestError error 1.)

这对我来说真的很困惑.是否在编译时决定在传递给printIt的结构上调用哪个方法,而不管它实际是什么类型?

此外:Swift编程指南中记录的类和结构之间的运行时行为有何不同,有人可以参考该部分吗?我还没有找到任何东西.

在第一个示例中,您将覆盖description属性.因此,将此实现添加到OddString的vtable(因为它是一个类),并且可以动态调度到恰好,无论实例静态类型是什么.

在你的第二个例子中,你没有一个类 – 所以没有vtable.但是,您符合协议.协议允许通过协议见证表进行动态调度(参见this great WWDC talk),但这仅适用于协议要求的实现.

localizedDescription不是Error协议的协议要求,它只是在导入Foundation时在Error的协议扩展中定义(这在SE-0112中有记录).因此无法动态调度.相反,它将被静态调度 – 因此调用的实现依赖于实例的静态类型.

这就是你在这里看到的行为 – 当你的爆炸性实例被输入为TestError时,你会调用localizedDescription的实现.当键入为Error时,将调用Error扩展中的实现(它只是桥接到NSError并获取其localizedDescription).

如果要提供本地化描述,则应将错误类型符合LocalizedError,将errorDescription定义为协议要求 – 从而允许动态调度.有关如何解决此问题的示例,请参阅this Q&A.

总结

以上是内存溢出为你收集整理的Swift中的动态/运行时调度,或“奇怪的结构行为在一个人看来”全部内容,希望文章能够帮你解决Swift中的动态/运行时调度,或“奇怪的结构行为在一个人看来”所遇到的程序开发问题。

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

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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存