Làm thế nào để bạn ghi đè đúng isEqual:
trong Objective-C? "Bắt" dường như là nếu hai đối tượng bằng nhau (như được xác định bởi isEqual:
phương thức), chúng phải có cùng giá trị băm.
Phần Introspection của Hướng dẫn cơ bản về ca cao có một ví dụ về cách ghi đè isEqual:
, sao chép như sau, đối với một lớp có tên MyWidget
:
- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![other isKindOfClass:[self class]])
return NO;
return [self isEqualToWidget:other];
}
- (BOOL)isEqualToWidget:(MyWidget *)aWidget {
if (self == aWidget)
return YES;
if (![(id)[self name] isEqual:[aWidget name]])
return NO;
if (![[self data] isEqualToData:[aWidget data]])
return NO;
return YES;
}
Nó kiểm tra sự bằng nhau của con trỏ, sau đó là đẳng thức lớp và cuối cùng so sánh các đối tượng sử dụng isEqualToWidget:
, chỉ kiểm tra các thuộc tính name
và data
. Những gì ví dụ không hiển thị là làm thế nào để ghi đè hash
.
Giả sử có những tính chất khác không ảnh hưởng đến sự bình đẳng, nói age
. Không nên hash
ghi đè phương thức đó chỉ name
và data
ảnh hưởng đến hàm băm? Và nếu vậy, bạn sẽ làm điều đó như thế nào? Chỉ cần thêm băm của name
và data
? Ví dụ:
- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}
Như vậy đã đủ chưa? Có một kỹ thuật tốt hơn? Điều gì nếu bạn có người nguyên thủy, như thế int
nào? Chuyển đổi chúng để NSNumber
có được băm của họ? Hay cấu trúc như thế NSRect
nào?
( Brain fart : Ban đầu được viết "bitwise HOẶC" chúng cùng với |=
. Thêm vào.)
if (![other isKindOfClass:[self class]])
- Về mặt kỹ thuật này có nghĩa là bình đẳng sẽ không được giao hoán. Tức là A = B không có nghĩa là B = A (ví dụ: nếu một người là lớp con của người khác)