启用数组类型

时间:2018-03-21 12:45:28

标签: swift switch-statement

概述

我想通过匹配数组类型来使用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

问题:

  • 我怎样才能做到这一点?

1 个答案:

答案 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执行一个完全动态的强制转换,它会在运行时调度,最终会调用上述转换函数。

虽然为什么编译器不能暂时将这些强制转换视为完全动态强制转换,直到必要的专用逻辑到位,但我不太确定。