簡體   English   中英

約束協議的關聯類型本身

[英]Constrain protocol's associated type itself

我正在嘗試創建通用的CollectionView數據源。 我有兩個協議,第一個-一個抽象單元格,第二個表明某個抽象單元格可以表示符合類,並且應該只包含引用該單元格的關聯類型。 它們的實現可能如下所示:

protocol EntityPresentingCell {

    // entity that should be presented in this cell
    associatedtype T

    static var CellReuseID: String { get }

    // takes object and fill UI with data
    func populate(with object: T)
}

protocol CellPresentable {

    // cell that should present this entity
    // I need to constrain it
    associatedtype Cell: EntityPresentingCell // where Cell.T == Self
}

class CollectionViewDataSource<T: CellPresentable>: NSObject, UICollectionViewDataSource {

    var items: [T]

    init(items: [T]) {
        self.items = items
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: T.Cell.CellReuseID, for: indexPath)

        // compiler error here since, obviously, T.Cell.T not constrained to T itself
        (cell  as! T.Cell).populate(with: items[indexPath.item])
        return cell
    }

}

在使用時,它可能看起來像這樣:

class SomeEntity: CellPresentable {
    typealias Cell = SomeEntityCell

    var someValue = "someValue"
}

class SomeEntityCell: EntityPresentingCell {

    static var CellReuseID: String = "SomeID"

    @IBOutlet weak var label: UILabel!

    func populate(with object: SomeEntity) {
        label.text = object.someValue
    }

}

這段代碼的問題是,我無法約束CellPresentable.Cell.T(因此確保在編譯時確保它)等於CellPresentable本身(例如示例)。 可以清楚地看到編譯器錯誤。

目標是制作純粹的編譯時全能代碼,以證明該項目可以在給定的單元格中顯示出來(再次在編譯時),而我不想強制向下轉換或進行任何其他運行時檢查。

可能嗎? 如果是這樣,怎么辦?

UPD: David Rodrigues的答案有效,但這意味着不匹配(T.Cell.T != T)僅在我要創建CollectionViewDataSource時才會顯示。 我希望在定義我的實體對EntityPresentingCell協議的符合性時發生。 換句話說,當我寫類似的東西時,編譯器應該抱怨

class SomeEntity: CellPresentable {
    typealias Cell = SomeWrongEntityCell

    var someValue = "someValue"
}

但是當我創建CollectionViewDataSource實例時卻沒有。 確保單元格類型是實體的責任,而不是CollectionViewDataSource的創建者。

Swift 4更新

現在,您可以將where Cell.T == Self約束添加到關聯的類型,因此,您現在確實可以說:

protocol CellPresentable {
    associatedtype Cell : EntityPresentingCell where Cell.T == Self
}

迅捷3

當前,除了需要遵守的約束之外,不可能對關聯的類型添加任何其他約束。

但是,現在SE-0142:允許約束關聯類型的where子句已被接受,在以后的Swift版本中,可以在關聯類型中添加where子句。

應該只能說:

protocol CellPresentable {
    associatedtype Cell : EntityPresentingCell where Cell.T == Self
}

盡管在實現之前, David的添加通用約束( where T.Cell.T == T 的解決方案)的解決方案可能與您將要獲得的效果where T.Cell.T == T

您可以約束T.Cell.T等於T

class CollectionViewDataSource<T: CellPresentable>: NSObject, UICollectionViewDataSource where T.Cell.T == T

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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