通用数组的Swift错误

时间:2015-02-28 21:15:46

标签: swift generics

我有一个非常简单的游乐场:

protocol MyProtocol {}

struct MyType: MyProtocol {}

class MyClass <T: MyProtocol> {
    func myFunction(array: [T]) {
        if let myArray = array as? [MyType] {
            println("Double!")
        }
    }
}

let instance = MyClass<MyType>()

let array = [MyType(), MyType()]

instance.myFunction(array)

然后它在MyType is not a subtype of 'T'行上显示“if let”。不过,我认为,MyTypeT是兼容的。

当我修改if let语句时,它实际上有效:

if let first = array.first as? MyType

但现在我无法将array转换为[MyType](当然,我知道它是Swift的静态类型规范。)

我想知道问题是什么。我对泛型的理解?或者是Swift语言的限制?如果是这样,有没有办法这样做?

提前致谢。

2 个答案:

答案 0 :(得分:4)

Swift没有内置行为来推测性地将数组的内容从一种任意类型转换为另一种类型。它只会对它知道具有子类型/超类型关系的两种类型执行此操作:

class A { }
class B: A { }
let a: [A] = [B(),B()]
// this is allowed - B is a subtype of A
let b = a as? [B]

let a: [AnyObject] = [1,2,3]
// this is allowed - NSNumber is a subtype of AnyObject
let b = a as? [NSNumber]

struct S1 { }
struct S2 { }

let a = [S1(),S1()]
// no dice - S2 is not a subtype of S1
let b = a as? [S2]

该协议也无济于事:

protocol P { }
struct S1: P { }
struct S2: P { }

let a = [S1(),S1()]
// still no good – just because S1 and S2 both conform to P
// doesn’t mean S2 is a subtype of S1
let b = a as? [S2]

您的示例基本上是最后一个的变体。您有一个类型为[T]的数组,并且您希望将其强制转换为[MyType]。重要的是要了解您具有[MyProtocol]类型的数组。您的通用类型T是一种特定类型,必须实现MyProtocol,但这不是一回事。

要了解为什么不能从任何类型转换为任何其他类型,请尝试以下代码:

protocol P { }
struct S: P { }

let a: [P] = [S(),S()]
let b = a as? [S]

这会产生一个运行时错误:&#34;致命错误:不同类型的不同类型之间的不安全的生成错误&#34;。这给出了一个提示,说明为什么只能将包含一个引用类型的数组转换为子类型 - 这是因为发生的事情只是从一个指针类型转换为另一个指针类型。这适用于超类/子类,但不适用于任意类,结构或协议,因为它们具有不同的二进制表示。

答案 1 :(得分:3)

子类型上的泛型不是父类型上相同泛型的子类型。

Swift中的

[MyProtocol]实际上转换为Array<MyProtocol>(即通用)。 [MyType]作为Array< MyType >的快捷方式也是如此。这就是为什么一个人不直接投射到另一个人。