【问题标题】:Constrain protocol's associated type itself约束协议的关联类型本身
【发布时间】:2016-10-16 07:25:37
【问题描述】:

我正在尝试创建通用的 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 answer 有效,但这意味着只有在我即将创建 CollectionViewDataSource 时才会显示不匹配的 (T.Cell.T != T)。我希望它恰好在我定义我的实体符合EntityPresentingCell 协议时发生。换句话说,当我写类似的东西时,编译器应该抱怨

class SomeEntity: CellPresentable {
    typealias Cell = SomeWrongEntityCell

    var someValue = "someValue"
}

但不是在我创建 CollectionViewDataSource 实例时。确保单元格类型是实体的责任,而不是CollectionViewDataSource 的创建者。

【问题讨论】:

  • @Hamish 这是我问题的答案,如果你把它写成答案,我会接受。
  • 我已将评论移至答案 :)

标签: ios swift generics associated-types


【解决方案1】:

Swift 4 更新

您现在可以将where Cell.T == Self 约束添加到关联类型,因此您现在确实可以说:

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

斯威夫特 3

目前,除了需要遵守的约束之外,无法向关联类型添加任何进一步的约束。

不过,既然SE-0142: Permit where clauses to constrain associated types 已被接受,那么在未来的 Swift 版本中将可以将where 子句添加到关联类型。

应该只能说:

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

尽管在此实现之前,David's solution 添加通用约束 where T.Cell.T == T 可能与您将获得的一样好。

【讨论】:

    【解决方案2】:

    您可以将T.Cell.T 限制为等于T

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

    【讨论】:

    • 这是我尝试的第一件事并且它有效,但这意味着绑定T.Cell.T == T发生在CollectionViewDataSource的创建时,但我希望它发生在定义CellPresentable
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多