概览
我想通过匹配数组类型来使用 switch 语句。我有以下类(class)。
类:
class A {}
class B : A {}
开启单值工作:
let a : A = B()
switch a {
case let b as B:
print("b = \(b)")
default:
print("unknown type")
}
开启阵列(编译错误):
let aArray : [A] = [B(), B()]
switch aArray {
case let bArray as [B] :
print("bArray = \(bArray)")
default:
print("unknown type")
}
错误:
Downcast pattern value of type '[B]' cannot be used
注意在 Swift 4
上测试问题:
- 我怎样才能做到这一点?
最佳答案
在 Swift 4.1 中,您会收到更好的错误消息(感谢 #11441 ):
Collection downcast in cast pattern is not implemented; use an explicit downcast to '[B]' instead
简而言之,您遇到了一些尚未完全实现的编译器,其进度由错误跟踪 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]
为什么会这样?首先,介绍一下背景。数组、字典和集合由 Swift 的转换机制特殊处理——尽管它们是泛型类型(默认情况下是不变的),Swift 允许您在不同元素类型的集合之间进行转换(有关更多信息,请参阅 this Q&A)。
实现这些转换的函数驻留在标准库中(例如,Array
的 implementation is here )。在编译时,Swift 将尝试识别集合向下转换(例如 [A]
在您的示例中为 [B]
)以便它可以直接调用上述转换函数,并避免必须通过 Swift 运行时进行完整动态转换。
但是问题在于,这种专用逻辑并未针对集合向下转换模式(例如在您的示例中)实现,因此编译器会发出错误。通过首先强制转换为 Any
,我们强制 Swift 执行完全动态的转换,通过运行时进行调度,最终将调用上述转换函数。
虽然在必要的专用逻辑到位之前,为什么编译器不能暂时将此类转换视为完全动态转换,但我不太确定。
关于swift - 开启数组类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49406684/