Swift协议中如何为关联类型添加Equatable约束?
问题:为DeckDelegate协议的find方法添加Equatable约束报错
尝试给DeckDelegate协议中的find方法添加where Element: Equatable约束时,出现错误:Instance method requirement 'find' cannot add constraint 'Self.Element: Equatable' on 'Self',相关代码如下:
protocol DeckDelegate: AnyObject { associatedtype Element var size: Int { get } var isEmpty: Bool { get } var cards:[Element] { get set } func push(_ element: Element) func pop() -> Element? func find(_ card: Element) -> Int? where Element: Equatable } class Deck<Element> { func find(_ card: Element) -> Int? where Element : Equatable { return cards.firstIndex(of: card) } var size: Int { return cards.count } var isEmpty: Bool { return (cards.count == 0) } internal var cards: [Element] = [] func push(_ element: Element) { cards.append(element) } func pop() -> Element? { // TBD } }
解决方案
Swift不允许在协议的单个方法要求上直接给关联类型添加约束,你可以通过以下两种方式解决:
方式一:给协议关联类型添加全局Equatable约束
如果希望所有遵循DeckDelegate的类型,其Element都必须符合Equatable,可以直接把约束加到协议的关联类型上:
protocol DeckDelegate: AnyObject { associatedtype Element: Equatable // 将约束移至关联类型定义处 var size: Int { get } var isEmpty: Bool { get } var cards:[Element] { get set } func push(_ element: Element) func pop() -> Element? func find(_ card: Element) -> Int? // 无需再添加where约束 }
这种方式下,find方法可以直接依赖Element的Equatable特性,所有实现该协议的类都必须保证其Element类型是可比较的。
方式二:通过协议扩展实现条件性的find方法
如果不想强制所有DeckDelegate的Element都必须是Equatable,仅在Element符合Equatable时才提供find方法,可以用协议扩展结合条件一致性:
1. 修改协议,移除find方法的约束要求
protocol DeckDelegate: AnyObject { associatedtype Element var size: Int { get } var isEmpty: Bool { get } var cards:[Element] { get set } func push(_ element: Element) func pop() -> Element? }
2. 给协议添加带约束的扩展
extension DeckDelegate where Element: Equatable { func find(_ card: Element) -> Int? { return cards.firstIndex(of: card) } }
3. 让Deck类遵循协议
class Deck<Element>: DeckDelegate { var cards: [Element] = [] func push(_ element: Element) { cards.append(element) } func pop() -> Element? { return cards.popLast() // 补充实现 } // 当Element为Equatable时,自动继承扩展中的find方法,也可按需重写 }
这种方式更灵活:当Deck的泛型参数Element符合Equatable时,会自动拥有find方法;若Element不可比较,则该方法不会存在,避免不必要的约束。
内容的提问来源于stack exchange,提问作者zardon
相关产品推荐
相关产品推荐

