В Swift оператор == используется для проверки равенства двух значений. Для того чтобы этот оператор можно было использовать с пользовательскими типами, тип должен соответствовать протоколу Equatable и реализовывать статическую функцию ==.
Реализация должна быть симметричной и транзитивной. Пример:
struct Person: Equatable { let name: String let age: Int static func ==(lhs: Person, rhs: Person) -> Bool { return lhs.name == rhs.name && lhs.age == rhs.age } }
Стоит помнить, что если ваш тип не реализует ==, то попытка сравнения двумя такими экземплярами приведет к ошибке компиляции.
Вопрос: Если структура или класс наследует протокол Equatable, почему иногда оператор == можно не реализовывать явно?
Ответ: Для структур, все свойства которых также соответствуют Equatable, Swift автоматически синтезирует реализацию оператора ==. Но если в типе есть свойства, не являющиеся Equatable, или тип — класс с кастомным наследованием, синтез не произойдет, и потребуется реализовать оператор вручную.
struct Point: Equatable { var x: Int var y: Int // Реализация == не нужна, он синтезируется автоматически }
История
В одном проекте разработчик добавил свойство типа
UIImageв структуру, уже соответствующуюEquatable. Ошибка компиляции возникла, потому чтоUIImageне реализуетEquatable, а значит, для структуры нельзя было автоматически синтезировать==. Решение — реализовать оператор==вручную, сравнивая только существенные для логики свойства.
История
Ошибка возникла после внесения нового свойства в структуру, но забыв добавить его сравнение в пользовательский оператор
==. Это привело к некорректной логике при работе с коллекциями и багам в пользовательском фильтре.
История
В проекте был написан custom-класс без реализации
Equatable, но его попытались использовать в Set. Это привело к runtime-ошибке, так как Set требует, чтобы элементы были уникальны (и, следовательно,Equatable).