use*_*037 5 switch-statement swift
我想通过匹配数组类型来使用switch语句.我有以下课程.
class A {}
class B : A {}
Run Code Online (Sandbox Code Playgroud)
let a : A = B()
switch a {
case let b as B:
print("b = \(b)")
default:
print("unknown type")
}
Run Code Online (Sandbox Code Playgroud)
let aArray : [A] = [B(), B()]
switch aArray {
case let bArray as [B] :
print("bArray = \(bArray)")
default:
print("unknown type")
}
Run Code Online (Sandbox Code Playgroud)
Downcast pattern value of type '[B]' cannot be used
Run Code Online (Sandbox Code Playgroud)
注意:在Swift 4上测试过
在Swift 4.1中,您会收到更好的错误消息(感谢#11441):
收集铸造模式中的向下转换未实现; 使用显式向下转换为"[B]"
简而言之,您正在尝试一些尚未完全实现的编译器,其中的进度由错误SR-5671跟踪.
但是,您可以Any在执行强制转换之前通过强制转换来解决此限制:
class A {}
class B : A {}
let aArray : [A] = [B(), B()]
switch aArray /* or you could say 'as Any' here depending on the other cases */ {
case let (bArray as [B]) as Any:
print("bArray = \(bArray)")
default:
print("unknown type")
}
// bArray = [B, B]
Run Code Online (Sandbox Code Playgroud)
为什么这样做?首先,有点背景.数组,字典和集合由Swift的转换机制专门处理 - 尽管是泛型类型(默认情况下是不变的),Swift允许您在不同元素类型的集合之间进行转换(有关详细信息,请参阅此问答).
实现这些转换的函数驻留在标准库中(例如,此处Array的实现在此处).在编译时,斯威夫特将尝试确定收集向下转换(例如,[A]到[B]在你的例子),所以它可以直接调用上述转换功能,并避免做一个全面通过斯威夫特运行时动态转换.
但问题是这种专用逻辑没有实现收集向下转换模式(例如在您的示例中),因此编译器会发出错误.通过首先强制执行Any,我们强制Swift执行一个完全动态的强制转换,它会在运行时调度,最终会调用前面提到的转换函数.
虽然为什么编译器不能暂时将这些强制类型转换为完全动态转换,直到必要的专用逻辑到位,但我不太确定.
对于任何有同样问题的人,它已在 Swift 5.8 中得到修复。
打开数组(原始代码)可以正常编译。
正如《Hacking with swift》中提到的,您现在可以执行以下操作:
class Pet { }
class Dog: Pet {
func bark() { print("Woof!") }
}
func bark(using pets: [Pet]) {
switch pets {
case let pets as [Dog]:
for pet in pets {
pet.bark()
}
default:
print("No barking today.")
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
464 次 |
| 最近记录: |