arrays - 泛型类的类型化数组

标签 arrays swift generics

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

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]'

有什么方法可以创建类型比 [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被限制为 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"

关于arrays - 泛型类的类型化数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32374453/

相关文章:

javascript - 在 JavaScript 中读取数组的 `length` 属性真的是一项昂贵的操作吗?

c++ - 如何每行打印特定数量的数组元素?

ios - Swift 通用函数来推送任何 View Controller

java - Spring BeanUtils 无法实例化泛型类

c# - xml 用它的泛型类型序列化一个泛型类

arrays - 使用 random() [Swift, Linux] 打乱字符串数组

javascript - 使用 javascript 从数组中选择某些元素

swift - 如何使用 NSSortDescriptor 进行多层嵌套关系

swift - 如何在 Swift 中使用选择器 View 值?

java - 带有扩展的泛型