因为Equatable
有Self
的要求,所以不应该直接在协议上实现。否则,该协议将作为一种类型不可用。
要在协议级别实现Equatable
,但能够使用该协议作为类型,则可以使用类型擦除。
为了演示,我修改了您的操场中给出的代码来构建橡皮擦。
因为我使用的方法的详细说明,请参阅这个职位上我的博客:
https://khawerkhaliq.com/blog/swift-protocols-equatable-part-two/
这里是你的游乐场修改后的代码:
protocol CustomProtocol {
var title: String { get }
var subtitle: String { get }
func isEqualTo(_ other: CustomProtocol) -> Bool
func asEquatable() -> AnyEquatableCustomProtocol
}
extension CustomProtocol where Self: Equatable {
func isEqualTo(_ other: CustomProtocol) -> Bool {
guard let o = other as? Self else { return false }
return self == o
}
func asEquatable() -> AnyEquatableCustomProtocol {
return AnyEquatableCustomProtocol(self)
}
}
struct A: CustomProtocol, Equatable {
var title: String
var subtitle: String
static func ==(lhs: A, rhs: A) -> Bool {
return lhs.title == rhs.title && lhs.subtitle == rhs.subtitle
}
}
struct B: CustomProtocol, Equatable {
var title: String
var subtitle: String
static func ==(lhs: B, rhs: B) -> Bool {
return lhs.title == rhs.title && lhs.subtitle == rhs.subtitle
}
}
struct AnyEquatableCustomProtocol: CustomProtocol, Equatable {
var title: String { return value.title }
var subtitle: String { return value.subtitle }
init(_ value: CustomProtocol) { self.value = value }
private let value: CustomProtocol
static func ==(lhs: AnyEquatableCustomProtocol, rhs: AnyEquatableCustomProtocol) -> Bool {
return lhs.value.isEqualTo(rhs.value)
}
}
// instances typed as the protocol
let a: CustomProtocol = A(title: "First title", subtitle: "First subtitle")
let b: CustomProtocol = B(title: "First title", subtitle: "First subtitle")
let equalA: CustomProtocol = A(title: "First title", subtitle: "First subtitle")
let unequalA: CustomProtocol = A(title: "Second title", subtitle: "Second subtitle")
// equality tests
print(a.asEquatable() == b.asEquatable()) // prints false
print(a.asEquatable() == equalA.asEquatable()) // prints true
print(a.asEquatable() == unequalA.asEquatable()) // prints false
点需要注意的是,通过这种方法,实际的==
比较被委托给底层的具体类型,但我们只处理协议类型以维护抽象。
在这里,我只使用了擦除类型的实例来进行一次比较。但是,由于类型橡皮擦符合CustomProtocol
,因此可以在任何需要协议类型的地方保存和使用这些实例。因为它们符合Equatable
,所以它们也可以用于任何需要符合要求的地方。
只是为了背景下,这篇文章解释了为什么这是不可取的尝试直接在协议执行Equatable
一致性,甚至==
功能:
https://khawerkhaliq.com/blog/swift-protocols-equatable-part-one/
因此,类型擦除。
希望这会有所帮助。
您需要从更新的协议声明中删除相等函数,因为它们只在扩展中需要。 – Ollie
比较https://stackoverflow.com/q/41298464/2976878 – Hamish