1

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

我不明白为什么当类继承/不继承Equatable协议时 Swift 编译器的行为不一样。

这里是继承 Equatable 协议时的类

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”。这是预期的行为。

接下来,当我从类中删除“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 {

带有以下消息:“可选类型'测试的值?' 未解包;您的意思是使用“!”还是“?”?

为什么有/没有 Equatable 的行为不同?

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

当类继承 Equatable 时,将非可选与可选进行比较是否安全?

4

2 回答 2

1

==运营商

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? 操作数。因此编译器错误。

于 2017-11-01T16:31:32.780 回答
1

如果您命令单击符合 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 的版本,你不会得到这个。它只会使用您提供的静态函数。

于 2017-11-01T16:31:58.353 回答