AnyCollection([1, 2, 3]) // AnyCollection<Int>
AnyCollection(["a", "b", "c"]) // AnyCollection<String>
这两个AnyCollection
非常棒,但是它们具有不同的泛型类型,即Int
和String
。
但我仍然可以将这两个AnyCollection
添加到单个数组中,如下所示
// [AnyCollection<Any>]
let array = [AnyCollection([1, 2, 3]), AnyCollection(["a", "b", "c"])]
我不明白这两个AnyCollection
发生了什么。
为什么可以从String
或Int
转换为Any
?
我自己写了一些代码来创建一个。
// ❌ Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional
// Contains AnyMyCollection<String> && AnyMyCollection<Int> at a single collection.
var collections = [AnyMyCollection(Sports()), AnyMyCollection(Animals()), AnyMyCollection(Digits())]
protocol MyCollection<Element> {
associatedtype Element
func allValues() -> [Element]
}
// MARK: - AnyMyCollection
struct AnyMyCollection<Element> {
internal var _box: _AnyMyCollectionBase<Element>
init<C: MyCollection>(_ base: C) where C.Element == Element {
self._box = _MyCollectionBox(base)
}
}
extension AnyMyCollection: MyCollection {
func allValues() -> [Element] {
_box.allValues()
}
}
final class _MyCollectionBox<Base: MyCollection>: _AnyMyCollectionBase<Base.Element> {
init(_ base: Base) {
_base = base
}
private var _base: Base
override func allValues() -> [Base.Element] {
_base.allValues()
}
}
class _AnyMyCollectionBase<Element>: MyCollection {
func allValues() -> [Element] {
return []
}
}
// MARK: - Diffrent Types of My Collection
struct Animals: MyCollection {
typealias Element = String
func allValues() -> [Element] {
["Monkey", "Tiger", "Lion"]
}
}
struct Sports: MyCollection {
typealias Element = String
func allValues() -> [Element] {
["Basketball", "Football", "Baseball"]
}
}
struct Digits: MyCollection {
typealias Element = Int
func allValues() -> [Element] {
[1, 2, 3, 4, 5]
}
}
我尝试采用相同的技术,但失败了,因为AnyMyCollection
中元素的类型不相同。
1条答案
按热度按时间yb3bgrhw1#
简单的解释是,你不是苹果。
泛型一般不会协变参数化类型,而且你无法创建一个 * 协变参数化类型的泛型。* 但是Apple可以。*
为了更简单地理解这一点,考虑一下Array。它是一个泛型。如果你有两个类,一个类和它的子类,你可以合并它们中每一个的数组:
编译器接受这一点;它将得到的组合视为超类
Array<Array<MyClass>>
的数组的数组,因此对于Apple来说,Array<MySubclass>
被视为Array<MyClass>
的子类。但是现在试着用你自己的仿制药来做,你做不到:
编译器不会神奇地将其视为
Array<MyGeneric<MyClass>>
,因为 your 泛型不是协变的。总有一些语言提案坐在那里,希望让我们普通人能够制造协变泛型,但到目前为止,还没有一个提案进入语言。