繁体   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