[英]swift: AnyCollection with different generic types
AnyCollection([1, 2, 3]) // AnyCollection<Int>
AnyCollection(["a", "b", "c"]) // AnyCollection<String>
這兩個AnyCollection
很棒,但是它們有不同的 Generic 類型,即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
中的元素類型不相同。
簡單的解釋就是你不是蘋果。
Generics 通常不在參數化類型上協變,並且您無法創建在參數化類型上協變的泛型。 但蘋果有。
要更簡單地了解這一點,請考慮 Array。 這是一個通用的。 如果你有兩個類,一個 class 及其子類,你可以將它們中的每一個組合成 arrays:
class MyClass {}
class MySubclass: MyClass {}
let arr1 = [MyClass()]
let arr2 = [MySubclass()]
let arr3 = [arr1, arr2] // [[MyClass]]
編譯器接受這個; 它將生成的組合視為超類Array<Array<MyClass>>
的 arrays 數組。 因此對於 Apple, Array<MySubclass>
被視為Array<MyClass>
的一種子類。
但現在嘗試用你自己的通用來做到這一點。 你不能這樣做:
class MyGeneric<T> {}
let g1 = MyGeneric<MyClass>()
let g2 = MyGeneric<MySubclass>()
let arr4 = [g1, g2] // error
編譯器不會神奇地將其視為Array<MyGeneric<MyClass>>
。 那是因為你的泛型不是協變的。
總是有語言的提議,希望能讓我們普通人做出協變 generics。但到目前為止,還沒有一個進入語言。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.