考虑以下简化的协议(protocol)/类层次结构
protocol P {
}
class A: P {
}
class B: P {
}
class C<T: P> {
}
我想创建类 C
实例的类型化数组。然而,自动类型推断似乎不起作用。当我这样做时
let objs = [C<A>(), C<B>()]
let obj = objs[0]
objs
和 obj
分别是 [AnyObject]
和 AnyObject
类型。我本来期望类似的东西
let objs:[C<P>] = [C<A>(), C<B>()]
可以工作,但无法编译并出现错误
Using 'P' as a concrete type conforming to protocol 'P' is not supported
像这样完全省略泛型类型
let objs:[C] = [C<A>(), C<B>()]
编译时产生不同的错误
Cannot convert value of type 'NSArray' to specified type '[C]'
有什么方法可以创建类型比 [AnyObject]
更具体的 C
实例数组吗?
最佳答案
考虑以下代码:
// DOES NOT WORK!!
protocol P {
var name: String { get }
}
class A: P {
var name = "A"
}
class B: P {
var name = "B"
}
class C<T: P> {
var val: T
init(val: T) {
self.val = val
}
}
let objs: [C<P>] = [ C<A>(A()) ]
let firstObj: C<P> = obj[0]
firstObj.val = B()
在本例中,firstObj
实际上是一个C<A>
实例。但是firstObj.val
必须接受B()
因为firstObj.val
被限制为 P
和B
符合P
。你知道这是违法的。这就是为什么你不能施放 C<A>
如C<P>
例如,要解决此问题,您可以围绕 C
创建一些包装器:
protocol P {
var name: String { get }
}
class A: P {
var name = "A"
}
class B: P {
var name = "B"
}
class C<T: P> {
var val: T
init(_ val: T) {
self.val = val
}
}
/// Type erasing wrapper around C that has accessor for `C.val`
struct AnyC {
let _val: () -> P
var val: P { return _val() }
init<T>(_ c: C<T>) {
_val = { return c.val }
}
}
let objs:[AnyC] = [
AnyC( C<A>(A()) ),
AnyC( C<B>(B()) ),
]
objs[0].val.name // -> "A"
objs[1].val.name // -> "B"
关于arrays - 泛型类的类型化数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32374453/