我遇到了一个难以理解的问题,但我想问问了解它的可能性。
此代码由帮助我解决另一个问题的人提供:
protocol Proto { var value: String { get } }
extension URLError: Proto { var value: String { return "hello" } }
func value(_ error: Error) {
if let error = error as? Proto {
print("proto", error.value)
} else {
print(":(")
}
}
我除了运行时多态之外,转换应该起作用,并且proto hello
在传递URLError
对象时应该打印以下调用:
value(URLError(.badURL))
但这是我得到的,在 Swift 5.0 中,铸造工作,在 Swift 5.3 中,铸造不起作用。
在这里尝试 replit.com 进行个人测试和演员工作
swift 版本是 5.0.x,如图所示:
我在本地操场上测试了代码,铸造不起作用,我的快速版本是:
Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
此外,提供代码的人在他的机器上安装了 Swift 5.4,并且铸造对他也不起作用。
希望哪位能回复一下,写的更简单,适合初学者。
更新
某人告诉我
尝试将其添加为 value() 中的第一行: print(type(of: error)) 你可能会对它打印出来的内容感到惊讶。
如果在这里有帮助,我想分享我的回复:
我确实有想过它会在两个版本中打印什么。
对于 5.0 版,它打印:
URLError
proto hello
在 5.3 版中,它打印:
NSError
:(
我有一个答案,为什么以下表达式有效:
let error = URLError(.badURL) as NSError
print(type(of: a)) // NSError
这适用于 Swift 的两个版本。
它与 swift 中的自动桥接有关,swift 中存在一系列类型,它们在 Objective-c 中具有对应的类型。NSString
<-->String
是另一个示例。
所以,我相信这是因为结构URLError
符合Error
协议,而类NSError
符合Error
协议,所以就像Error
协议是这种转换的桥梁......我觉得它有点道理。
但是,我是一个URLError
演员,Error
在运行时被问到你实际上是什么类型
我应该回答我NSError
吗?!是NSError
介于两者之间吗?
Swift 5.0 确实看到了 URLError 的实际对象,但 Swift 5.3 没有。
当我将已经转换为 NSError 的对象传递给:
value(URLError(.badURL) as NSError)
然后他们俩都将其视为 NSError 然后结束:
print(type(of: error)) // NSError
我对此案感到有道理。
完成此评论后,我觉得这像是 5.0 中的错误行为并在更高版本中修复?并且一旦你构造了任何符合 Error 协议的类型,它的实际类型就从运行时检查中隐藏了?