Почему компилятор swift ведет себя иначе с оператором равенства с / без протокола Equatable
У меня есть очень простой класс на игровой площадке в Swift 4.0, который переопределяет оператор ==.
Я не понимаю, почему компилятор Swift не ведет себя так же, когда класс наследует / не наследует протокол Equatable.
Здесь класс при наследовании 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 не равно 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 {
со следующим сообщением: "Значение необязательного типа" Test? " не развернутый, вы хотели использовать "!" или "?"?
Почему поведение отличается с / без Equatable?
На самом деле, я также ожидал такую же ошибку компиляции, когда класс наследовал от Equatable, потому что я сравнивал необязательный с необязательным.
Безопасно ли сравнивать необязательный с необязательным, когда класс наследует Equatable?
2 ответа
E сть ==
оператор
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, вы этого не получите. Он будет использовать только статическую функцию, которую вы предоставили.