swift - Self: Equatable 不起作用的 Swift 协议扩展
问题描述
谁能阐明为什么这不起作用?我收到一个错误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 CustomEquatable { func isEqualTo(_ other: CustomEquatable) -> Bool }
让我们定义一些用于实验的类型:
struct A: Equatable {
let name: String
}
struct B: Equatable {
let id: Int
}
假设我们想要A
并B
遵守CustomEquatable
。那么我们有四种情况需要考虑:
- 什么
a1.isEqualTo(a2)
意思(wherea1
和a2
are both typeA
)? - 什么
b1.isEqualTo(b2)
意思(whereb1
和b2
are both typeB
)? - 是什么
a.isEqualTo(b)
意思(哪里a
是 aA
和b
是 aB
)? - 什么
b.isEqualTo(a)
意思(哪里b
是 aB
和a
是一个A
)?
对于前两种情况,可能的答案是a1.isEqualTo(a2)
当且仅当a1 == a2
且b1.isEqualTo(b2)
当且仅当b1 == b2
。
对于后两种情况,我们必须决定是否有办法让 aA
等于 a B
。最简单的解决方案(我认为)是 anA
永远不能等于 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?
)。所以我们可以将一致性分解到一个协议扩展中,如下所示:
extension CustomEquatable where Self: Equatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? Self) == self
}
}
有了这个协议扩展,我们可以在不为每个协议实现的情况下制定A
和B
遵守: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
推荐阅读
- python - 尝试启动 Firefox 浏览器时出现 Python Selenium 错误
- c++ - 38:10:错误:成员引用基类型“节点 *”不是结构或联合 *prev->next = temp;
- android - FirebaseAuth Facebook 登录返回黑屏
- javascript - D3.js - 使用 JSON 对象数据的正负条形图
- amazon-web-services - 如何将使用 AWS Amplify 作为后端的前端部署到生产环境
- r - 在R中将字符月列转换为年月格式
- r - 使用 R 在多个时间范围内求和
- java - 具有已定义行的 Oracle 嵌套选择
- django - 如何为每个用户制作个人资料
- spring-boot - 在 Springboot 中使用 Retrofit (Retrofit2) 客户端 (Kotlin) 实现双向 TLS