为什么 swift 编译器的行为与相等运算符不同 with/without Equatable 协议

why swift compiler behaves differently with equality operator with/without Equatable protocol

我在 Swift 4.0 的 Playground 中有一个非常简单的 class,它覆盖了 == 运算符。

我不明白为什么 Swift 编译器在 class inherits/doesn 不继承 Equatable 时表现不同协议。

这里是继承Equatable协议时的class

class Test: Equatable  {
    var value = 0

    init(_ initialValue:Int) {
        value = initialValue
    }

    static func == (lhs:Test, rhs:Test) -> Bool {
        return lhs.value == rhs.value ? true : false
    }
}

let test1 = Test(0)
var test4:Test? = nil

if test1 == test4 {
    print("test1 and test4 are equals")
} else {
    print("test1 not equals to test4")
}

执行此代码时显示 "test1 not equals to test4"。这是预期的行为。

接下来,当我刚刚从 class

中删除 "Equatable" 协议时
class Test  {
    var value = 0

    init(_ initialValue:Int) {
        value = initialValue
    }

    static func == (lhs:Test, rhs:Test) -> Bool {
        return lhs.value == rhs.value ? true : false
    }
}

let test1 = Test(0)
let test3 = Test(0)

var test4:Test? = nil


if test1 == test4 {
    print("test1 and test4 are equals")
} else {
    print("test1 not equals to test4")
}

我在

行遇到编译错误
if test1 == test4 {

带有以下消息:"Value of optional type 'Test?' not unwrapped; did you mean to use "!" 或 '?'?

为什么行为不同 with/without Equatable?

事实上,当 class 继承自 Equatable 时,我也期待同样的编译错误,因为我将非可选与可选进行比较。

当 class 继承 Equatable 时,比较非可选和可选是否安全?

有个== operator

public func ==<T>(lhs: T?, rhs: T?) -> Bool where T : Equatable

允许比较两个可选值 如果基础 类型是 Equatable. 在您的第一种情况下调用该运算符

let test1 = Test(0)
var test4:Test? = nil

if test1 == test4 { ... }

(左操作数自动包装成一个可选的。)

如果 Test 不符合 Equatable 则该运算符符合 不匹配,因此没有 == 运算符取两个 Test? 操作数。因此编译错误。

如果您点击符合 Equatable 的命令,它将带您到这里:

/// ....
/// You can also use this OPERATOR TO COMPARE A NON-OPTIONAL VALUE TO AN
/// OPTIONAL that wraps the same type. The non-optional value is wrapped as an
/// optional before the comparison is made. In the following example, the
/// `numberToMatch` constant is wrapped as an optional before comparing to the
/// optional `numberFromString`:
///
///     let numberToFind: Int = 23
///     let numberFromString: Int? = Int("23")      // Optional(23)
///     if numberToFind == numberFromString {
///         print("It's a match!")
///     }
///     // Prints "It's a match!"
///
/// ....
public func ==<T>(lhs: T?, rhs: T?) -> Bool where T : Equatable

但是对于不符合Equatable的版本,你不会得到这个。它只会使用您提供的静态函数。