简体   繁体   English

泛型类的类型化数组

[英]Typed array of generic classes

Consider the following simplified protocol/class hierarchy考虑以下简化的协议/类层次结构

protocol P {
}

class A: P {
}

class B: P {
}

class C<T: P> {
}

I want to create a typed array of instances of the class C .我想创建一个C类实例的类型化数组。 The automatic type inference does not seem to work, however.然而,自动类型推断似乎不起作用。 When I do当我做

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

objs and obj are of type [AnyObject] and AnyObject , respectively. objsobj是类型的[AnyObject]AnyObject分别。 I would have expected something like我会期待类似的东西

let objs:[C<P>] = [C<A>(), C<B>()]

to work but it doesn't compile with the error工作,但它没有编译错误

Using 'P' as a concrete type conforming to protocol 'P' is not supported

Omitting the generic type altogether like so像这样完全省略泛型类型

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

produces a different error on compilation编译时产生不同的错误

Cannot convert value of type 'NSArray' to specified type '[C]'

Is there any way I could create an array of C instances with a type more specific than [AnyObject] ?有什么方法可以创建一个类型比[AnyObject]更具体的C实例数组?

Consider following code:考虑以下代码:

// 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()

In this case, firstObj is actually a C<A> instance.在这种情况下, firstObj实际上是一个C<A>实例。 But firstObj.val must accept B() because firstObj.val is constrained to P and B conforms to P .但是firstObj.val必须接受B()因为firstObj.val被约束到PB符合P This is illegal you know.你知道这是违法的。 That is why you cannot cast C<A> as C<P>这就是为什么你不能将C<A>C<P>

To workaround this, for example, you can create some wrapper around the C :例如,要解决此问题,您可以围绕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"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM