簡體   English   中英

swift:具有不同泛型類型的 AnyCollection

[英]swift: AnyCollection with different generic types

AnyCollection([1, 2, 3]) // AnyCollection<Int>
AnyCollection(["a", "b", "c"]) // AnyCollection<String>

這兩個AnyCollection很棒,但是它們有不同的 Generic 類型,即IntString

但我仍然可以將這兩個AnyCollection添加到一個數組中,就像這樣

// [AnyCollection<Any>]
let array = [AnyCollection([1, 2, 3]), AnyCollection(["a", "b", "c"])] 

我不明白這兩個AnyCollection發生了什么。

為什么它可以從StringInt轉換為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM