Swift 协议(protocol)扩展,其中 Self : Equatable doesn't work

标签 swift generics swift-protocols

谁能解释为什么这不起作用?我收到错误消息 Binary operator '==' cannot be applied to operands of type 'Self' and 'CustomEquatable'

protocol CustomEquatable {
    func isEqualTo(_ other: CustomEquatable) -> Bool
}

extension CustomEquatable where Self: Equatable {
    func isEqualTo(_ other: CustomEquatable) -> Bool {
        return self == other
    }
}

最佳答案

让我们从您的CustomEquatable 协议(protocol)开始,没有扩展:

protocol CustomEquatable {
    func isEqualTo(_ other: CustomEquatable) -> Bool
}

让我们定义一些用于实验的类型:

struct A: Equatable {
    let name: String
}

struct B: Equatable {
    let id: Int
}

假设我们希望 AB 符合 CustomEquatable。那么我们有四种情况要考虑:

  • a1.isEqualTo(a2) 是什么意思(其中 a1a2 都是 A 类型)?
  • b1.isEqualTo(b2) 是什么意思(其中 b1b2 都是 B 类型)?
  • a.isEqualTo(b) 是什么意思(其中 a 是一个 Ab 是一个B)?
  • b.isEqualTo(a) 是什么意思(其中 b 是一个 Ba 是一个A)?

对于前两种情况,可能的答案是 a1.isEqualTo(a2) 当且仅当 a1 == a2b1.isEqualTo(b2 ) 当且仅当 b1 == b2

对于后两种情况,我们必须决定是否有办法让 A 等于 B。最简单的解决方案(我认为)是 A 永远不能等于 B

所以我们可以这样写一致性:

extension A: CustomEquatable {
    func isEqualTo(_ other: CustomEquatable) -> Bool {
        return (other as? A) == self
    }
}

extension B: CustomEquatable {
    func isEqualTo(_ other: CustomEquatable) -> Bool {
        return (other as? B) == self
    }
}

这两个一致性的唯一区别是转换类型(在 as? 的右侧)。所以我们可以将一致性分解成这样的协议(protocol)扩展:

extension CustomEquatable where Self: Equatable {
    func isEqualTo(_ other: CustomEquatable) -> Bool {
        return (other as? Self) == self
    }
}

有了这个协议(protocol)扩展,我们可以让AB符合CustomEquatable,而不用为每个实现isEqualTo :

extension A: CustomEquatable { }
extension B: CustomEquatable { }

测试代码:

let a1 = A(name: "a1")
let a2 = A(name: "a2")
let b1 = B(id: 1)
let b2 = B(id: 2)

a1.isEqualTo(a1) // true
a1.isEqualTo(a2) // false
b1.isEqualTo(b1) // true
b1.isEqualTo(b2) // false
a1.isEqualTo(b1) // false
b1.isEqualTo(a1) // false

关于Swift 协议(protocol)扩展,其中 Self : Equatable doesn't work,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52935322/

相关文章:

ios - swift ,iOS : How to use UIButton to trigger UIAlertController

c# - 是否可以组合不同类型的委托(delegate)(使用返回值作为参数)?

ios - 我的模板/通用 Swift 初始化程序/构造函数有什么问题?

ios - 将泛型 AnyObject 向下转换为协议(protocol)关联类型 Self.Model

swift - 如何在另一个上显示分数文本编号?

swift macOS : Window-Redraw is not working

ios - 没有 UIViewController 的 UITableView

c# - 是否可以在引入其他泛型类型的泛型类上使用构造函数?

c# - 使用接口(interface)作为泛型方法的类型参数

ios - 'CLLocationCoordinate2D' 与协议(protocol) 'decodable'/'encodable' 的冗余一致性