类型的泛型类数组

时间:2015-09-03 11:31:46

标签: arrays swift generics

考虑以下简化的协议/类层次结构

protocol P {
}

class A: P {
}

class B: P {
}

class C<T: P> {
}

我想创建类C的类型化实例数组。但是,自动类型推断似乎不起作用。当我做的时候

let objs = [C<A>(), C<B>()]
let obj = objs[0]

objsobj分别属于[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]'

有没有什么方法可以创建一个C个实例数组,其类型比[AnyObject]更具体?

1 个答案:

答案 0 :(得分:2)

请考虑以下代码:

// 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被限制为PB符合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"