如何使用协议的任何关键字来符合 Equatable?

Moc*_*cha 0 swift

我想让我的协议符合 Equatable。但是,每当我使用该协议时,我都会收到错误Type any {protocol} does not conform to Equatable.

protocol ExampleDataProtocol: Equatable {
  var someData: Int { get set }
}

public extension ExampleDataProtocol {
  static func ==(lhs: any ExampleDataProtocol, rhs: any ExampleDataProtocol) -> Bool {
    return lhs.someData == rhs.someData
  }

  static func ==(lhs: Self, rhs: Self) -> Bool {
    return lhs.someData == rhs.someData
  }
}

struct SomeStruct: Equatable { // Type 'SomeStruct' does not conform to protocol 'Equatable'
  var someData: any ExampleDataProtocol
}
Run Code Online (Sandbox Code Playgroud)

当我手动添加协议存根时,我any ExampleDataProtocol 对 Equatable 感到不舒服。

struct SomeStruct: Equatable {
  static func == (lhs: SomeStruct, rhs: SomeStruct) -> Bool {
    lhs.someData == rhs.someData // Type 'any ExampleDataProtocol' cannot conform to 'Equatable'
  }

  var someVar: any ExampleDataProtocol
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*ier 5

协议不符合协议。他们可能需要其他协议,但他们不遵守这些协议。DataProtocol 不是 Equatable。它要求符合类型是 Equatable。

存在主义any DataProtocol也不符合等值律。存在性从不遵守协议,但在这种情况下,Equatable 要求它的两个参数具有完全相同的类型(Self),而不是“符合此协议的东西”。您的扩展提供了一个==函数,但它没有Equatable所需的签名:

static func == (lhs: Self, rhs: Self) -> Bool
Run Code Online (Sandbox Code Playgroud)

注意这里的自我。这与 不是一回事any DataProtocol。该扩展将方法附加到符合类型。存在(any)包装了一个符合 DataProtocol 的值,但它本身并不符合 DataProtocol。(有一天我预计any类型可能符合某些协议,但它们可能永远无法符合具有 Self 要求或静态方法的协议,而 Equatable 两者都有。)

您可以这样实现您所描述的内容:

extension DataProtocol {
    // This compares `self` to any other DataProtocol, not just Self.
    func isEqual(to other: some DataProtocol) -> Bool {
        return data == other.data
    }
}

struct SomeStruct {
    var someData: any DataProtocol
}

extension SomeStruct: Equatable {
    static func == (lhs: SomeStruct, rhs: SomeStruct) -> Bool {
        lhs.someData.isEqual(to: rhs.someData)
    }
}
Run Code Online (Sandbox Code Playgroud)