Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 相互矛盾的协议符合性_Swift_Protocols_Swift5 - Fatal编程技术网

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我已将该评论的内容移到了答案中。请查收。这有意义吗?