首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Objective-C 物件比較:同一性 vs 等值性 深度解析

     編輯:關於C語言

核心概念區分

術語英文定義檢查方式
同一性Identity兩個變數指向同一個記憶體位址 (同一實例)== 指標比較
等值性Equality兩個不同實例但邏輯內容相同isEqual: 或型別專用方法

快速範例

NSString *a = @"hello";
NSString *b = a;           // 同一物件
NSString *c = [NSString stringWithString:@"hello"]; // 不同實例,內容相同

NSLog(@"a == b : %d", a == b);   // 1 (同一性)
NSLog(@"a == c : %d", a == c);   // 0 (不同實例)
NSLog(@"[a isEqual:c] : %d", [a isEqual:c]); // 1 (等值性)

NSObject 協定

@protocol NSObject
- (BOOL)isEqual:(id)object;
- (NSUInteger)hash;          // 等值物件必須有相同 hash
@end
  • 預設實作:isEqual: 內部呼叫 ==,即僅判斷同一性。
  • 子類責任:覆寫 isEqual: 實作邏輯比較,同步覆寫 hash,否則放入 NSSet/NSDictionary 會失效。

Foundation 常見類別的等值性實作

類別比較依據專用方法
NSString逐字元 Unicode 比較isEqualToString: (效能較佳)
NSArray元素數量相同且逐項 isEqual:—
NSDictionary鍵值對數量相同、鍵 isEqual:、值 isEqual:—
NSNumber數值型別轉換後比較—
NSDate時間間隔相等isEqualToDate:
NSData位元組序列相同isEqualToData:

自訂類別實作範本

// Person.h
@interface Person : NSObject
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) NSUInteger age;
@end

// Person.m
@implementation Person

- (BOOL)isEqual:(id)object {
    if (self == object) return YES;                    // 同一性快速路徑
    if (![object isKindOfClass:[Person class]]) return NO; // 型別檢查

    Person *other = (Person *)object;
    return [self.name isEqual:other.name] && self.age == other.age;
}

- (NSUInteger)hash {
    // 組合雜湊,確保等值物件 hash 相同
    return [self.name hash] ^ (self.age << 1);
}

@end

常見陷阱與最佳實踐

❌ 陷阱 1:只覆寫 isEqual: 忘記 hash

Person *p1 = [[Person alloc] initWithName:@"A" age:20];
Person *p2 = [[Person alloc] initWithName:@"A" age:20];
NSSet *set = [NSSet setWithObjects:p1, p2, nil];
NSLog(@"%lu", (unsigned long)set.count); // 輸出 2 (預期 1) —— hash 不同導致視為不同元素

❌ 陷阱 2:isEqual: 不對稱

[a isEqual:b] != [b isEqual:a]  // 違反等價關係,容器行為未定義

修正:先檢查 isKindOfClass:,再比較屬性。

✅ 最佳實踐清單

  1. 優先使用專用比較方法 (isEqualToString: 等),避免動態派發開銷。
  2. 覆寫 isEqual: 時必須覆寫 hash。
  3. hash 組合方式:return [prop1 hash] ^ ([prop2 hash] << 1) ^ ...。
  4. 不可變物件快取 hash (如 NSString) 提升效能。
  5. 集合類別 (NSArray 等) 已正確實作深層比較,直接信任。

進階:NSComparisonMethods 協定

若需排序,實作 compare: 回傳 NSComparisonResult:

- (NSComparisonResult)compare:(Person *)other {
    NSComparisonResult nameCmp = [self.name compare:other.name];
    if (nameCmp != NSOrderedSame) return nameCmp;
    return (self.age < other.age) ? NSOrderedAscending : NSOrderedDescending;
}

總結

同一性 = 指標相等 (==),極快;
等值性 = 語義相等 (isEqual:),需正确实作 hash。
記住黃金法則:if ([a isEqual:b]) assert([a hash] == [b hash]);

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved