Swift 通用数组错误
Swift error with generic array
我有一个非常简单的游乐场:
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)
然后在 if let
行显示“MyType is not a subtype of 'T'
”。嗯,不过,我认为 MyType
和 T
是兼容的。
当我修改if let
语句时,它确实有效:
if let first = array.first as? MyType
但现在我无法将 array
转换为 [MyType]
(当然,我知道这是 Swift 的静态类型规范。)
我想知道问题出在哪里。我对泛型的理解?或者是 Swift 语言的限制?如果是这样,有什么办法可以这样做吗?
提前致谢。
Swift 没有内置行为来推测将数组的内容从一种任意类型转换为另一种。它只会对它知道具有 subtype/supertype 关系的两种类型执行此操作:
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]
这将产生一个运行时错误:"fatal error: can't unsafeBitCast between types of different sizes"。这暗示了为什么您只能将包含一种引用类型的数组转换为子类型——这是因为发生的事情只是从一种指针类型转换为另一种指针类型。这将适用于 super/subtype 类,但不适用于任意 类、结构或协议,因为它们具有不同的二进制表示形式。
子类型上的泛型不是父类型上相同泛型的子类型。
[MyProtocol]
in Swift 实际上转换为 Array<MyProtocol>
(即通用)。 [MyType]
也是 Array< MyType >
的快捷方式。这就是为什么一个不直接转换为另一个的原因。
我有一个非常简单的游乐场:
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)
然后在 if let
行显示“MyType is not a subtype of 'T'
”。嗯,不过,我认为 MyType
和 T
是兼容的。
当我修改if let
语句时,它确实有效:
if let first = array.first as? MyType
但现在我无法将 array
转换为 [MyType]
(当然,我知道这是 Swift 的静态类型规范。)
我想知道问题出在哪里。我对泛型的理解?或者是 Swift 语言的限制?如果是这样,有什么办法可以这样做吗?
提前致谢。
Swift 没有内置行为来推测将数组的内容从一种任意类型转换为另一种。它只会对它知道具有 subtype/supertype 关系的两种类型执行此操作:
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]
这将产生一个运行时错误:"fatal error: can't unsafeBitCast between types of different sizes"。这暗示了为什么您只能将包含一种引用类型的数组转换为子类型——这是因为发生的事情只是从一种指针类型转换为另一种指针类型。这将适用于 super/subtype 类,但不适用于任意 类、结构或协议,因为它们具有不同的二进制表示形式。
子类型上的泛型不是父类型上相同泛型的子类型。
[MyProtocol]
in Swift 实际上转换为 Array<MyProtocol>
(即通用)。 [MyType]
也是 Array< MyType >
的快捷方式。这就是为什么一个不直接转换为另一个的原因。