簡體   English   中英

Objective-c中的“測試類平等”

[英]“Testing Class Equality” in Objective-c

我在理解蘋果指南中定義的“測試類平等”的這一部分時遇到了問題。

在動態創建的子類中,通常會重寫類方法,以便子類偽裝成它所替換的類。 因此,在測試類相等性時,應該比較類方法返回的值而不是低級函數返回的值。 就API而言,以下不等式適用於動態子類:

 [object class] != object_getClass(object) != *((Class*)object) 

因此,您應該測試兩個類的相等性,如下所示:

 if ([objectA class] == [objectB class]) { //... 

在某些情況下,人們會在運行時添加新類。 一個例子是Key Value Observing:當你觀察一個對象時,Foundation框架會創建一個被觀察對象類的新子類。 此動態類的行為與其超類的行為相同,但將KVO通知添加到其所有mutator方法。

你引用的段落說,Objective-C運行時可以告訴這個新類與原始類不同。 但是,因為它只是KVO構建方式的實現細節,所以您不應該知道或關心它。 因此開發人員覆蓋了他們新類的-class方法,假裝對象仍然是原始類的成員。

如果要檢查兩個對象是否屬於同一個類,則必須比較它們的-class方法的結果(將KVO等技巧考慮在內),而不是使用運行時函數。

這是一個例子:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSObject *observer = [NSObject new];
        NSObject *model = [NSObject new];

        [model addObserver: observer forKeyPath: @"count" options: 0 context: NULL];

        //using -class methods:
        NSLog(@"model is a %@, observer is a %@", [model class], [observer class]);

        //casting to Class:
        NSLog(@"model is a %@, observer is a %@", *(Class*)model, *(Class*)observer);

        //using the runtime:
        NSLog(@"model is a %@, observer is a %@", object_getClass(model), object_getClass(observer));

        [model removeObserver: observer forKeyPath: @"count" context: NULL];
        [model release];
        [observer release];
    }
    return 0;
}

你看到我正在做的就是創建兩個對象,告訴其中一個對象,然后找出他們的類是什么。 結果如下:

2012-06-08 08:37:26.904 Untitled 2 [896:707]模型是NSObject,觀察者是NSObject

2012-06-08 08:37:26.907 Untitled 2 [896:707]模型是NSKVONotifying_NSObject,觀察者是NSObject

2012-06-08 08:37:26.907 Untitled 2 [896:707]模型是NSKVONotifying_NSObject,觀察者是NSObject

因此,正如文檔所示,它只是第一種情況(我們比較-class ),它可以完成應用程序代碼可以合理預期的任何事情。 找到類的另外兩種方法 - 詢問運行時,並將對象指針強制轉換為Class * - 都提供了關於KVO如何從我們下面改變類的實現細節,並且意味着類比較現在不會表明班級是平等的。

因為其他答案和評論指的是-isMemberOfClass:-isKindOfClass:我也將覆蓋這些點:

  • -isKindOfClass: 不是類相等的測試。 如果objectaClass 或其任何子類的實例,則[object isKindOfClass: aClass]為true。 因為你引用的段落是關於類相等的, -isKindOfClass:與此無關。 也就是說,它通常是您希望在應用程序代碼中進行的測試。 關心“我可以將這個物體用作Foo嗎?”的答案更為常見。 比“這個對象真的是Foo的實例嗎?”。

  • -isMemberOfClass:是類相等的測試: [object isMemberOfClass: aClass]僅當object是aClass的實例時才為true。 這個測試是使用-class方法的結果完成的,這意味着在這個例子中, model 將為 [model isMemberOfClass: [NSObject class]]測試為正。

它應該是:

if([objctA isKindOfClass [MyClass class]])

也許你可以使用'NSStringFromClass'方法並比較獲得的字符串,感謝'isEqualToString'?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM