iOS Judge object Equality rewrite isequal, Isequaltoclass, hash

Source: Internet
Author: User

The concept of equality is to explore the core of philosophy and mathematics, and has a profound influence on the problems of morality, justice and public policy.

From an empirical point of view, two objects cannot be distinguished by some observation criteria, they are equal. On the humanities side, the egalitarian view is that equality means keeping everyone's society, economy, politics, and the justice system at their residence consistent.

It is a task for programmers to coordinate logical and sensory abilities to understand the ' same ' semantics that we shape. ' The same problem ' (the discussion) is too subtle and too easy to be overlooked. To realize it without sufficient understanding of righteousness may lead to unnecessary work and incorrect results. Therefore, a deep understanding of the mathematical and logical systems is also necessary in order to achieve the desired plan.

While all of the technical posts are tempting to read its title and code, please take a few minutes to read and understand the text. Copying the seemingly useful code verbatim, without knowing why it is likely to cause some errors. Equality is one of the important topics, but it still contains a lot of confusing concepts, especially in objective-c.

Equality & Identity

First, it is important to clarify the difference between equality and identity. If two objects have the same observed properties, they can be equated with each other. However, the two objects can still distinguish between the differences, their respective identity. In a program, the identity of an object is associated with its memory address.

NSObject object Test and another object is the same use isEqual: method, in its basic implementation of the sex check is essentially an identity check, if two objects point to the same memory address, they are considered equal.

@implementation NSObject (Approximate)- (BOOL)isEqual:(id)object { return self == object;}@end

For built-in classes, like Nsarray, Nsdictionary, and NSString, a deep equality comparison is performed to test that each element in the collection is equal, which is a very useful practice to do.

NSObject subclasses to implement their own isEqual: methods, the following points should be achieved:

    • 1. Implement a isEqualTo__ClassName__: method to perform a meaningful comparison of values.

      2. Override isEqual: the method to make a type and object identity check, and callback the value comparison method above.

      3. Rewrite the hash, this will be explained in the next section.

Here's a general idea for Nsarray to implement this (this example ignores the cluster, and the actual implementation is more concrete and complex):

@implementation Nsarray (approximate)-(BOOL) Isequaltoarray: (Nsarray *)array {if (! Array | | [self count]! = [array count]) {return NO;} for (nsuinteger idx = 0; idx < [array count]; idx++) {
             
              if (![ 
              self[idx] isequal:ARRAY[IDX]]) {return NO;}} return YES;} -(BOOL) IsEqual: (ID) object {if (self = = object) {if (![ Object Iskindofclass:[nsarray class]] {return NO;} return [self isequaltoarray: (Nsarray *) object];} @end           
                   

The following subclass of NSObject in Foudation has custom-defined implementations, using the relevant methods:

NSAttributedString -isEqualToAttributedString:NSData -isEqualToData:NSDate -isEqualToDate:NSDictionary -isEqualToDictionary:NSHashTable -isEqualToHashTable:NSIndexSet -isEqualToIndexSet:NSNumber -isEqualToNumber:NSOrderedSet -isEqualToOrderedSet:NSSet -isEqualToSet:NSString -isEqualToString:NSTimeZone -isEqualToTimeZone:NSValue -isEqualToValue:

When comparing two instances of any of these classes, it is isEqual: recommended to use their own high-level method instead of
However, our theoretical implementation is not yet complete, and now let's turn our attention to hash (an episode: Clean up the nsstring problem first).

NSString, the odd case of the award.

An interesting episode, take a look at this code:

*a = @"Hello";NSString *b = @"Hello";BOOL wtf = (a == b); // YES

Solemnly declare that the correct comparison of the two NSString object equality method is to use the -isEqualToString: method, in any case can not be compared with the == operator two nsstring.

So what's going on here? Why Nsarray or nsdictionary the same literal is not so, and it (NSString) will do so.

This is a kind of optimization technique known as ' string Dwell ', because the different values of this optimization can be copied from a backup of an immutable string value. The nsstring type a pointer and B refer to the same copy for the resident string @ "Hello". Note that this optimization is valid only for statically declared immutable strings.

More interestingly, the selector name of OC is also stored as a resident string in a pooled string pool.

Hashing

In the most routine object-oriented programming, the most important usage of object judgment is to decide the members of a collection. To make this step faster, the classes implemented by custom judgments should also be hashed:

    • 1. Object equality is mutual ([a isequal:b]⇒[b isequal:a])

      2. If the objects are equal, their hash values must be equal ([a isequal:b]⇒[a hash] = = [B hash])

      However, the reverse is not necessarily true: if their hash value is equal, two objects are not necessarily equal. ([a hash] = = [b hash]¬⇒[a isequal:b])

Now take a quick look at "Computer Science" 101:

The basic data structure in hash table programming, which enables Nsset & Nsdictionary to find its elements quickly (O (1)). We can also get a good understanding of the hash table by comparing the arrays:

Arrays stores elements According to an ordered index, so an array of size n will place the elements in the index until n-1. To determine where an element in the array exists, it is necessary to check each position one at a time (unless the array happens to be sorted, but this is another thing).

The hash table uses a slightly different approach. Instead of storing the elements sequentially, the hash table allocates n locations in memory, and a function is used to calculate a position within that range. A hash function is deterministic, and a good hash function uses a relatively uniform hash to generate values, and there is not much computational process. When two different objects calculate the same hash value, a hash conflict is generated. When a conflict occurs, the hash table looks for a conflict point and puts the newly added object in the first available position. When the hash table becomes more and more crowded, the likelihood of conflict increases, which can lead to more time spent looking for space (which is why the hash function of uniform hashing is not expensive.) )

A false consensus about implementing the hash function comes from the ensuing assertion that the hash value must be different. This erroneous consensus can lead to unnecessarily complex implementations, including the magical mantra of prime numbers copied from Java textbooks. In fact, a simple XOR (XOR) of the hash value of a key attribute is sufficient for 99% of cases.

The trick is to think about which value in the object is critical. For NSDate, the time interval for the reference date is sufficient:

@implementation NSDate (Approximate)- (NSUInteger)hash {  return (NSUInteger)abs([self timeIntervalSinceReferenceDate]);}

For Uicolor, the RGB value after the shift is very convenient to calculate for a uicolor, a bit-shifted sum of RGB, a convenient calculation:

@implementation UIColor (Approximate)- (NSUInteger)hash {  CGFloat red, green, blue; [self getRed:&red green:&green blue:&blue alpha:nil]; return ((NSUInteger)(red * 255) << 16) + ((NSUInteger)(green * 255) << 8) + (NSUInteger)(blue * 255);}@end
Implement-isequal in subclasses: and hash

Together, here's an example of how to override the default implementation in subclasses:

@interfacePerson@propertyNSString *name;@propertyNSDate *birthday;-(BOOL)Isequaltoperson: (person *) person;@end@implementationperson-(BOOL)Isequaltoperson: (Person *) Person {if (!person) {ReturnNO; }BOOL Haveequalnames = (!Self.name &&!person.name) | | [Self.nameIsEqualToString:person.name];BOOL haveequalbirthdays = (!Self.birthday &&!person.birthday) | | [Self.birthdayIsEqualToDate:person.birthday];return haveequalnames && haveequalbirthdays;}  #pragma mark-nsobject-(bool) isequal: (ID) object {if (self = = object) {return YES; } if (![ Object iskindofclass:[person class]]) {return NO;} return [self isequaltoperson: ( person *) object];} -(nsuinteger) hash {return [self.name hash] ^ [ span class= "keyword" >self.birthday hash];}            

iOS Judge object equality override IsEqual, Isequaltoclass, hash

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.