1.every object has only hash, not equal other object?
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
obj1.hash != obj2.hash
object'hash base on what?
2.object's hash never change when I change object's properties???
or
(object init after object's hash can't change ???)
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
NSObject *obj3 = [[NSObject alloc] init];
NSDictionary *dic = @{@(obj1.hash):obj1,@(obj2.hash):obj2,@(obj3.hash):obj3,...};
other(English is not my native language,grammar mistake forgive me)
As @Sulthan says, the default implementation of hash is the address of object
.
In your subclass, you can override -hash
method, you may calculate the hash according to your properties, if so, when you change the property, the hash
will change.
For example: NSMutableString
, you can check the log to see the result, when you change the content of NSMutableString
, its hash changed.
NSMutableString *s = [[NSMutableString alloc] initWithString:@"124"];
NSLog(@"%@", @([s hash]));
[s appendString:@"123"];
NSLog(@"%@", @([s hash]));
When you override hash
method and add the instance of that class into a collection which use object's hash to locate object, you must make sure the hash function never change.
In Apple's documentation, it talks about the hash
method in NSObject protocol :
If two objects are equal (as determined by the isEqual: method), they must have the same hash value. This last point is particularly important if you define hash in a subclass and intend to put instances of that subclass into a collection. If a mutable object is added to a collection that uses hash values to determine the object’s position in the collection, the value returned by the hash method of the object must not change while the object is in the collection. Therefore, either the hash method must not rely on any of the object’s internal state information or you must make sure the object’s internal state information does not change while the object is in the collection. Thus, for example, a mutable dictionary can be put in a hash table but you must not change it while it is in there. (Note that it can be difficult to know whether or not a given object is in a collection.)
Here is an example:
@interface Object : NSObject
@property (nonatomic) NSInteger ttt;
@end
@implementation Object
- (NSUInteger)hash {
return _ttt;
}
@end
NSMutableSet *set = [NSMutableSet set];
Object *obj = [[Object alloc] init];
obj.ttt = 10;
[set addObject:obj];
obj.ttt = 9;
[set addObject:obj];
NSLog(@"%@", @(set.count));
The result is 2 even the obj
is the same object. The reason is that NSMutableSet use hash
to determine if there already exists a object in the set. You can imagine there is a simple hash table, obj
locates at 10 when it is first inserted into the set. Then you change ttt
property to 9, its hash changed, NSMutableSet
finds the position at 9 is empty, so it inserted the object again at 9.