Swift provides powerful tools for comparing and equating custom objects using the Comparable and Equatable protocols.
In this tutorial, we will explore how to use the Comparable protocol to compare custom objects based on their properties, and the Equatable protocol to determine whether two objects are equal.
By the end of this tutorial, you will have a better understanding of how to implement these protocols in your own code and how they can be used to add functionality to your custom classes.
If you are interested in video lessons on how to write Unit tests and UI tests to test your Swift mobile app, check out this page: Unit Testing Swift Mobile App
The == Operator
The == operator in Swift is used to compare the values of two instances of a type for equality. It returns a Boolean value indicating whether the two values are equal or not. When comparing two instances of a custom class, the == operator compares the values of the instance properties of the two objects.
Here’s an example of how the == operator can be used to compare two instances of a custom class:
class Person { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } } let person1 = Person(name: "John", age: 30) let person2 = Person(name: "John", age: 30) if person1 == person2 { print("The two persons are equal.") } else { print("The two persons are not equal.") }
Output:
The two persons are not equal.
In this example, we create two instances of the Person
class with the same values for their name
and age
properties. We then use the == operator to compare the two objects, which returns false
because person1
and person2
reference different memory locations, even though they have the same property values.
The === Operator
The === operator in Swift is used to compare two instances of a reference type to see if they refer to the same object in memory. It returns a Boolean value indicating whether the two objects are the same or not.
Here’s an example of how the === operator can be used to compare two instances of a custom class:
class Person { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } } let person1 = Person(name: "John", age: 30) let person2 = person1 if person1 === person2 { print("person1 and person2 refer to the same object in memory.") } else { print("person1 and person2 do not refer to the same object in memory.") }
Output:
person1 and person2 refer to the same object in memory.
In this example, we create an instance of the Person
class and assign it to two different variables. We then use the === operator to compare the two variables, which returns true because they refer to the same object in memory.
Conforming a Custom Class to the Comparable Protocol in Swift
In Swift, we can make custom classes conform to the Comparable
protocol to enable comparison operations such as less than (<
), greater than (>
), and equal to (==
). By implementing the required comparison operators, we can define the logic for comparing instances of our custom class.
In this section, we’ll walk through an example of how to make a custom Friend
class conform to the Comparable
protocol in Swift and implement the comparison operators to compare instances of the Friend
class based on their age and name properties.
import Foundation class Friend : Comparable { let name : String let age : Int init(name : String, age: Int) { self.name = name self.age = age } } func < (lhs: Friend, rhs: Friend) -> Bool { return lhs.age < rhs.age } func > (lhs: Friend, rhs: Friend) -> Bool { return lhs.age > rhs.age } func == (lhs: Friend, rhs: Friend) -> Bool { var returnValue = false if (lhs.name == rhs.name) && (lhs.age == rhs.age) { returnValue = true } return returnValue }
The code defines a custom Friend
class that conforms to the Comparable
protocol in Swift.
- The
Friend
class has two instance properties:name
andage
, both of which are of typeString
andInt
, respectively. - The
init
method is used to initialize thename
andage
properties with the provided values. - The code defines three functions that implement the comparison operators for the
Friend
class:<
,>
, and==
. - The
<
function compares theage
property of the left-hand side (lhs
)Friend
object to theage
property of the right-hand side (rhs
)Friend
object. - The
>
function compares theage
property of thelhs
Friend
object to theage
property of therhs
Friend
object. - The
==
function checks if thename
andage
properties oflhs
are equal to thename
andage
properties ofrhs
. - Because the
Friend
class conforms to theComparable
protocol, it is possible to use the<
,>
, and==
operators to compare two instances of theFriend
class for less than, greater than, and equal to, respectively.
Comparing Custom Objects Conforming to the Comparable Protocol in Swift
In this section, we’ll compare instances of custom classes that conform to the Comparable
protocol using the comparison operators defined for the class. We’ll use the Friend
class example that we defined earlier and demonstrate how the ==
operator can be used to compare two objects based on their properties.
let friend1 = Friend(name: "Sergey", age: 35) let friend2 = Friend(name: "Sergey", age: 30) print("\Compare Friend object. Same person? (friend1 == friend2)")
Output:
false
The code creates two instances of the Friend
class, friend1
and friend2
, with different age properties but the same name property. The code then uses the ==
operator to compare the friend1
and friend2
objects, checking if they represent the same person.
Since the ==
operator has been implemented for the Friend
class, it checks whether the name
and age
properties of friend1
and friend2
are equal. In this case, since the age
property is different for the two objects, the comparison returns false
.
This demonstrates how we can compare instances of custom classes that conform to the Comparable
protocol using the comparison operators defined for the class. In this case, we used the ==
operator to check if two instances of the Friend
class represented the same person, based on their name
and age
properties.
Equatable Protocol VS Comparable Protocol
Swift provides two protocols for comparing custom types: Equatable
and Comparable
. While both of these protocols allow us to define custom comparison logic for our types, there are some important differences between the two that we should be aware of:
Equatable Protocol
The Equatable
protocol provides a way to compare two instances of a type for equality. It requires us to implement the ==
operator for our custom type, which takes two instances of the type as parameters and returns a Bool
value indicating whether the two instances are equal.
Here’s an example of a Person
class conforming to the Equatable
protocol:
class Person: Equatable { let name: String let age: Int init(name: String, age: Int) { self.name = name self.age = age } static func == (lhs: Person, rhs: Person) -> Bool { return lhs.name == rhs.name && lhs.age == rhs.age } } let person1 = Person(name: "John", age: 30) let person2 = Person(name: "John", age: 30) print(person1 == person2) // true
In this example, the Person
class conforms to the Equatable
protocol by implementing the ==
operator. The operator checks if the name
and age
properties of two instances of Person
are equal, and returns true
if they are.
Comparable Protocol
The Comparable
protocol provides a way to compare two instances of a type and determine their relative order. It requires us to implement three comparison operators for our custom type: <
(less than), >
(greater than), and ==
(equal to).
Here’s an example of a Friend
class conforming to the Comparable
protocol:
class Friend: Comparable { let name: String let age: Int init(name: String, age: Int) { self.name = name self.age = age } static func < (lhs: Friend, rhs: Friend) -> Bool { return lhs.age < rhs.age } static func == (lhs: Friend, rhs: Friend) -> Bool { return lhs.name == rhs.name && lhs.age == rhs.age } } let friend1 = Friend(name: "Sarah", age: 25) let friend2 = Friend(name: "Jack", age: 30) print(friend1 < friend2) // true
In this example, the Friend
class conforms to the Comparable
protocol by implementing the <
and ==
operators. The <
operator compares the age
properties of two instances of Friend
and returns true
if the left-hand side instance’s age is less than the right-hand side instance’s age.
Differences between Equatable and Comparable
The main difference between Equatable
and Comparable
is the type of comparison that they allow. Equatable
is used for checking equality between two instances of a type, while Comparable
is used for ordering two instances of a type relative to each other.
Additionally, while the Equatable
protocol requires us to implement only the ==
operator, the Comparable
protocol requires us to implement three comparison operators: <
, >
, and ==
. This makes the Comparable
protocol more powerful and flexible than the Equatable
protocol, as it allows us to perform more complex operations like sorting and searching. However, Equatable protocol only provides a way to check if two objects are equal or not.
Furthermore, remember the following:
- Use Equatable protocol when you only need to compare objects for equality. For example, if you have a custom class representing a user and you need to check if two user objects represent the same user, you can make the class conform to the Equatable protocol and implement the
==
operator. - Use Comparable protocol when you need to compare objects and order them based on their properties. For example, if you have a custom class representing a product and you need to sort a list of products based on their prices, you can make the class conform to the Comparable protocol and implement the
<
and>
operators.
To summarize, both protocols allow for object comparison, but Comparable is more powerful and versatile, while Equatable is simpler and only checks for equality. It’s important to choose the appropriate protocol based on your specific use case.
Conclusion
In conclusion, this tutorial provided a comprehensive overview of the Comparable protocol in Swift, and how to use it to compare custom objects. We explored the == and === operators, as well as how to conform a custom class to the Comparable protocol. We also covered the Comparable and Equatable protocols and discussed their differences.
If you want to continue learning about Swift, make sure to visit the Swift Tutorials page. This page provides a wealth of information and resources to help you improve your Swift skills and stay up-to-date with the latest advancements in the language.
Frequently asked questions
- What happens if I try to compare objects that do not conform to the Comparable protocol?
If you try to compare objects that do not conform to the Comparable protocol in Swift, you will get a compile-time error. This is because the Comparable protocol provides the necessary requirements for Swift to know how to compare two objects of the same type, and if those requirements are not met, the comparison operation will not work. - Can I implement both the Equatable and Comparable protocols in the same custom class?
Yes, it is possible to implement both the Equatable and Comparable protocols in the same custom class in Swift. By conforming to both protocols, you can define both equality and comparison behavior for your custom objects. However, it is important to ensure that the implementation of both protocols is consistent and does not cause any conflicts or unexpected behavior. - How does Swift determine the order of two objects when comparing them using the Comparable protocol?
When comparing two objects that conform to the Comparable protocol in Swift, the order is determined by the implementation of the < (less than) and > (greater than) operators in the custom class. If the < operator returns true, then the first object is considered to be less than the second object. Conversely, if the > operator returns true, then the first object is considered to be greater than the second object. If neither the < nor the > operator returns true, then the two objects are considered to be equal.