Swift 相互矛盾的协议符合性
请任何人解释一下,这里发生了什么:Swift 相互矛盾的协议符合性,swift,protocols,swift5,Swift,Protocols,Swift5,请任何人解释一下,这里发生了什么: struct Test { var value: Int } // ----------------------------------- protocol Test1: Equatable { var value: Int { get set } } extension Test1 { static func == (lhs: Self, rhs: Self) -> Bool { lhs.value == rh
struct Test {
var value: Int
}
// -----------------------------------
protocol Test1: Equatable {
var value: Int { get set }
}
extension Test1 {
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.value == rhs.value + 1
}
}
// -----------------------------------
protocol Test2: Equatable {
var value: Int { get set }
}
extension Test2 {
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.value == rhs.value + 2
}
}
// -----------------------------------
extension Test: Test1 {}
extension Test: Test2 {}
let a = Test(value: 5)
let b = Test(value: 5)
print(a == b) // true, which is unexpected
如果仅符合Test1
或仅符合Test2
的要求,则其工作正常。符合
Test1
和Test2
。起初我认为顺序很重要。但看起来它只是互相抵消了!没有任何警告。这是非常违反直觉的。注意:Test
符合equalable
不是因为您提供了两个扩展,而是因为自动生成的equalable
实现。正如您所说,如果只有这两个扩展,那么哪个==
是可均衡的实现将是不明确的
Test1
或Test2
协议扩展中的==
都不被调用。而是调用自动生成的equalable
实现。您可能还记得,=
运算符是为属性均为可等式的类型自动生成的,并声明为符合可等式本身
这是因为在扩展中声明的成员使用静态绑定,因此当同一成员有多个版本可用时,只有当编译时类型是扩展的类型时,才会选择在扩展中声明的版本。例如:
protocol P { }
class C : P { func f() { print("C") } }
extension P { func f() { print("P") } }
C().f() // C
(C() as P).f() // P
在a==b
中,a
和b
都是Test
,因此没有选择任何扩展运算符。但是,由于Test1
和Test2
都使用Self
,因此只能将它们用作通用约束,也不能强制转换到它们。因此,我认为您根本无法调用扩展中声明的==
无论如何,如果您希望看到一条错误消息,指出存在重复的==
运算符可用:
struct Test {
var value: Int
var x: Any? // now there is no auto-generated Equatable implementation!
}
错误:类型“Test”不符合协议“equalable”扩展
测试:Test1{}^
注:候选者完全匹配
static func == (lhs: Self, rhs: Self) -> Bool {
^
static func == (lhs: Self, rhs: Self) -> Bool {
^
注:候选者完全匹配
static func == (lhs: Self, rhs: Self) -> Bool {
^
static func == (lhs: Self, rhs: Self) -> Bool {
^
如果删除其中一个扩展名,则由于扩展名,Test
符合equalable
,因为不再存在歧义。因此,自动生成的实现不再是自动生成的,只有一个==
可供选择-在扩展中声明的一个。“因此,我认为您根本无法调用扩展中声明的==”。正如我在文章中提到的,如果只选择一个扩展,==该扩展名的值被调用。@Roman当然是。我的意思是“如果你保留两个分机,你就不能给他们中的任何一个打电话”。我在回复Roman Ryzhiy的评论中解释了原因。@Roman我已将该评论的内容移到了答案中。请查收。这有意义吗?