我想通过匹配数组类型来使用switch语句。我有以下课程。
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
答案 0 :(得分:6)
在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]
为什么这样做?首先,有点背景。数组,字典和集合由Swift的转换机制专门处理 - 尽管是泛型类型(默认情况下是不变的),Swift允许您在不同元素类型的集合之间进行转换(有关详细信息,请参阅this Q&A)。
实现这些转换的函数位于标准库中(例如,Array
的{{3}})。在编译时,Swift将尝试识别集合向下转换(例如,在您的示例中为[A]
到[B]
),以便它可以直接调用上述转换函数,并避免必须执行完整通过Swift运行时动态转换。
但问题是这个专用逻辑没有实现收集向下转换模式(例如在你的例子中),因此编译器会发出错误。首先强制转换到Any
,我们强制Swift执行一个完全动态的强制转换,它会在运行时调度,最终会调用上述转换函数。
虽然为什么编译器不能暂时将这些强制转换视为完全动态强制转换,直到必要的专用逻辑到位,但我不太确定。