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

痴心易碎 提交于 2019-12-11 06:54:27

问题


I have a very simple class in a Playground in Swift 4.0 that overrides the == operator.

I'm not understanding why the Swift complier doesn't behave the same when the class inherits/doesn't inherit Equatable protocol.

Here the class when inheriting Equatable protocol

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")
}

When this code executes it displays "test1 not equals to test4". It's the expected behavior.

Next, when I just remove the "Equatable" protocol from the class

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")
}

I get a compilation error on the line

if test1 == test4 {

with the following message: "Value of optional type 'Test?' not unwrapped; did you mean to use "!" or '?'?

Why the behavior is different with/without Equatable?

In fact, I was also expecting the same compilation error when the class inherits from Equatable because I compare a non-optional with an optional.

Is it safe to compare a non-optional with an optional when a class inherits Equatable ?


回答1:


There is a == operator

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

which allows to compare two optional values if the underlying type is Equatable. That operator is called in your first case

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

if test1 == test4 { ... }

(and the left operand is automatically wrapped into an optional.)

If Test does not conform to Equatable then that operator does not match, so that there is no == operator taking two Test? operands. Therefore the compiler error.




回答2:


If you command click on the one that conforms to Equatable it would take you to here:

/// ....
/// 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

But for the version that doesn't conform to Equatable, you don't get this. It will only use the static function you provided.



来源:https://stackoverflow.com/questions/47059252/why-swift-compiler-behaves-differently-with-equality-operator-with-without-equat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!