One of the things we often use when we do APP development is to determine if two objects are equal. For example, if two strings are equal. And the so-called equivalence has two meanings. One is the value is equal, and the other is the reference equality. If you are familiar with objective-c development, you will know that OBJECTIVE-C provides us with a series of isEqual:
methods to judge the value equality, and the = = equals number is used to judge the reference equality. Let's take a look at a objective-c example and get a better idea:
nsarray *arr1 = @[@ "Cat", @ "Hat", @ "app"];nsarray *arr2 = @[@" Cat ", @" Hat ", @" app "]; nslog (@ "Result%i", (arr1 = = arr2)); //result 0nslog (@ "Result%i", [ ARR1 ISEQUALTOARRAY:ARR2]); //result 1
In the above code, we have defined two arrays,arr1 and arr2 , which hold the same elements in both arrays. Next we compare them equally and output the results. The first time we used = = equals number to compare, the result of the return is 0, that is to say, the comparison failed. The reason to believe that some experienced students should understand, because in the objective-c = = comparison is a reference, because arr1 and arr2 are two different objects, so even if their values are the same, but their references are not the same. So = = comparison will fail. The second comparison is Nsarray's Isequaltoarray method, which is used to compare values because the values of the two arrays are the same, so the isequaltoarray comparison method returns 1.
<!--more--
equatable Protocol
We learned about the workings of the equality operation through OBJECTIVE-C, including the value equality and reference equality. Now let's go back to Swift. I believe that the students who have OBJECTIVE-C experience will be looking for isequal method, but will find that there is no isequal definition in Swift's native class.
If you want to have a more in-depth understanding of isequal, this article equality the detailed explanation. We don't have too much of a narrative here.
Swift does not provide a definition of the Iequal method, but instead uses an overloaded operator to handle equality judgments in a more natural way. Overloaded ==
operators are done through the Equatable protocol. We implement the overloads of the operators by implementing the methods in this protocol.
func ==(lhs: Self, rhs: Self) -> Bool
Swift has implemented its own array classes, called Array
, about Array
types, and this article has a detailed description of the Swift tips-array type. The types in Swift Array
implement the Equatable
protocol, so we can Array
compare instances of types by ==
operator:
var arr1 = ["cat","hat","app"]var arr2 = ["cat","hat","app"]println arr1 == arr2 // true
We have seen that the effect of direct use in Swift ==
isEqual:
is the same as the actual effect of the method in Objective-c. They all compare the values. This feature of Swift is slightly different from objective-c. Almost all of Swift's native classes implement the Equatable
protocol.
implementing the Equatable protocol
We now understand the agreement in Swift Equatable
. It is believed that careful classmates have discovered that we can compare instances in Swift because the ==
object of this symbolic operation implements the Equatable
protocol. What if we compare the use of objects that do not implement this Protocol ==
? We can take a look at this piece of code:
In the above code, we define a Name
class and instantiate the two objects of this class john
copy
. Then we used ==
to compare the two, then the compiler error. The reason is that our class does not implement the Equatable
protocol.
So here's a little bit of a change to this class:
class name: equatable {var FirstName:string? var lastname:string? init (firstName first:string, LastName Last: string) {self.firstname = First self.lastname = Last}}func == (Lhs:name, rhs:name), bool {return lhs.firstname = rhs.firstname && Lhs.lastname = = Rhs.lastname}
In our modification, we implemented the Equatable
protocol and implemented the func ==(lhs: Name, rhs: Name) -> Bool
method. The firstName
lastName
two Name objects are considered equal only if they are equal to each other.
After this modification, we can continue to use our previous judgments:
if john == copy { print("equal") //equal}
This time, the if
method in the statement print
was executed successfully.
Now we know that most of the classes in Swift have their own ==
implementations of the operators. So what if we want to compare the references of two objects to equality Now?
We can use the ObjectIdentifier
class to get the reference identity of the object, and we explicitly call the constructor of the class to get the object's reference and compare it:
if ObjectIdentifier(john) == ObjectIdentifier(copy) { print("equal")}else{ print("not equal") // not equal}
We used to ObjectIdentifier
get the reference address of the object, and we ObjectIdentifier
implemented the protocol itself, Equatable
so we ObjectIdentifier
can compare the converted objects to ==
determine whether the application is the same.
comparable
We have just introduced the Equatable
agreement, and it has a protocol associated with it Comparable
. Equatable
a protocol is a comparison of equality. Instead, the Comparable
order is compared. For example, a Double
class in Swift implements the Comparable
protocol:
var left:Double = 30.23var right:Double = 50.55if left < right { print("30.23 is less than 50.55")}
Implement the Comparable
class of the protocol, you can use >,<,<=,>=
these operators to compare. The definition of this agreement is as follows:
protocol Comparable { ... }func <=(lhs: Self, rhs: Self) -> Boolfunc >=(lhs: Self, rhs: Self) -> Boolfunc >(lhs: Self, rhs: Self) -> Bool
Do you think that to achieve the comparison operation, we have to implement all the methods in this. We might as well take a few minutes to look carefully at the definition of the agreement and think about it.
- First of all, there are four sequential comparison operators,,,
<=
>=
>
< can you look at this protocol, as if the definition of < is less?
- Then, we analyze the logical relationship of these operators,
>=
actually is a side >
==
-by-side relationship, if we implement the two operators, the actual >=
logic is clear. The >=
logic of this operator is generally the statement: return lhs > rhs || lhs == rhs
.
By the short analysis above, did we find a pattern? In fact, we can introduce the logic of other operators as long as we implement some operators. For example, with the definition of the interface above, Comparable
<=
and >
These two operators, we just need to implement one to deduce the other. For example, if we implement the >
operator, then the ' <= ' operator only needs to reverse the previous function.
So, the <=
implementation of our function requires just a similar implementation:
func <=(lhs: Self, rhs: Self) -> Bool { return !(lhs > rhs)}
Think about it, in fact, as long as the implementation ==
and <
operators, the other operators can be deduced through these two:
- >= can be
<
deduced through the logical inversion and ==
the logic or operation together.
- > can be
<
deduced by the logical inversion.
- <= can be
<
==
deduced through the logic or operation of the.
About this knowledge, there is a concept called strict full order , interested students can read.
So now the problem again, we actually as long as ==
the implementation and <
the logic of the method can complete the comparison operation, then the implementation of the other operators code, is actually the same. It seems a bit redundant.
And Swift is solving this problem for us, providing us with the default implementation of the agreement, and looking closely at the Swift documentation, we will find that in addition to the Comparable
protocol, a protocol is defined _Comparable
, and the former inherits from the latter. _Comparable
the agreement is defined as follows:
protocol _Comparable { ... }func <(lhs: Self, rhs: Self) -> Bool
We found that just what we lost <
here was found. _Comparable
is an example of the default protocol implementation mechanism provided in Swift. The _Comparable
default implementations for several other operators are provided in the Protocol >=,>,<=
.
Since Comparable
both the self _Comparable
and Equatable
the protocol are inherited, we only need to implement the <
==
two operators to complete the implementation of the comparison operation. Let's look at an example:
ClassName:Comparable {var firstName:Stringvar lastName:StringInit (firstName First:String,lastname Last:String) {Self.firstname = FirstSelf.lastname = Last}}Func = =(Lhs:name, Rhs:name)Bool {return lhs.firstname = = Rhs.firstname && Lhs.lastname = = Rhs.lastname}Func< (Lhs:name, Rhs:name)Bool {Return Lhs.firstname < Rhs.firstname && Lhs.lastname < Rhs.lastname}Let John =Name (firstName:"John", LastName:"Smith")Let Johnclone =Name (firstName:"John", LastName:"Smith")Let Jack =Name (firstName:"Jack", LastName:"Smith")Let Mary =Name (firstName:"Mary", LastName:"Williams")Print (John >= Jack)TruePrint (John <= Jack)TruePrint (John = = Jack)FalsePrint (John > Jack)FalsePrint (John < Jack)//falseprint (Jack < Mary) // Trueprint (John = = Johnclone) //true var names:array<Name> = [ Johnclone,mary,john,jack]//[{firstname "John" LastName "Smith"}, {FirstName "Mary" LastName "Williams"}, {firstName "John" LastName "Smith"}, {firstName "Jack" LastName "Smith"}]names.sort {(LHS, RHS), bool in return lhs > Rhs}//[{firstname" Mary "LastName" Williams "}, {FirstName" John "LastName" Smith "}, {FirstName" John "LastName" Smith "}, {firstName" Jack "LastName" Smith "}] /span>
We are here to implement the Comparable
protocol completely, we define a Name
class, and implement the <
and ==
protocol methods, one from the protocol _Comparable
and one from Equatable
the protocol. The Comparable
three comparison methods in the protocol already _Comparable
provide a default implementation in, so we don't have to do it all over again. (Note the underscore difference between the two comparable and _comparable, which is two different protocols.) )
hashable
The last one to mention is the hashable protocol. We should not be unfamiliar with the concept of Dictionary , so if an object wants to be a Dictionary key , then it needs to implement hashable Agreement.
The following classes in Swift implement the hashable protocol by default:
- Double
- Float, Float80
- Int, Int8, Int16, Int32, Int64
- UInt, UInt8, UInt16, UInt32, UInt64
- String
- Unicodescalar
- Objectidentifier
So instances of these classes can be used as Dictionary keys. Let's take a look at the definition of the hashable protocol:
protocol Hashable { ... }var hashValue: Int { get }
The definition is very simple, we only need to implement hashValue
the calculation method to define the hash value. On the optimization of the hash value we are another subject, so we only do a simple discussion here, will use the property of the class hash value again or operation to calculate the new hash value. Or take our Name class for example:
class Name: Comparable,Hashable { ... var hashValue: Int { return self.firstName.hashValue ^ self.lastName.hashValue }}
Next we'll use it as a key to the dictionary:
let john = name (firstName: "John", LastName: "Smith") let johnclone = Name (firstName: "John", LastName: "Smith") let jack = name (firstName: "Jack", LastName: "Smith") let mary = name ( FirstName: "Mary", LastName: "Williams") var namemap:[name: String] = [:]nameMap [John] = "Manager" namemap[jack] = "Stuff"
This article introduces the three Protocols in Swift, Equatable
Comparable
Hashable
Although we don't usually pay much attention to these protocols, but in our development work, they are no longer playing a role, our if statements, sorting operations, dictionaries and arrays of operations, are related to these several protocols. Most of the classes in Swift are basically implementing these protocols. It can be said that although we often forget them, but they are constantly around us. Knowing them will certainly help us a lot.
Swift Explore-A little exploration of the isequal in Swift