29

Apple ガイドで定義されている「クラスの平等性をテストする」のこの部分を理解するのに問題があります。

動的に作成されたサブクラスでは、クラス メソッドは通常、サブクラスが置き換えるクラスとしてマスカレードするようにオーバーライドされます。したがって、クラスが等しいかどうかをテストするときは、下位レベルの関数によって返される値ではなく、クラス メソッドによって返される値を比較する必要があります。API に関して言えば、次の不等式が動的サブクラスに関係します。

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

したがって、次のように 2 つのクラスが等しいかどうかをテストする必要があります。

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

3 に答える 3

42

実行時に新しいクラスを追加する状況があります。その一例が Key Value Observing です。オブジェクトを観察すると、Foundation フレームワークは、観察されたオブジェクトのクラスの新しいサブクラスを作成します。この動的クラスはスーパークラスと同じように動作しますが、すべてのミューテーター メソッドに KVO 通知を追加します。

あなたが引用した一節は、Objective-C ランタイムがこの新しいクラスを元のクラスと区別できることを示しています。ただし、これは KVO の構築方法の実装の詳細にすぎないため、知ったり気にしたりしないでください。そのため、開発者は-class新しいクラスのメソッドをオーバーライドして、オブジェクトがまだ元のクラスのメンバーであるかのように見せかけました。

したがって、2 つのオブジェクトが同じクラスであるかどうかを確認する場合は、-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;
}

私がしているのは、2 つのオブジェクトを作成し、一方に他方を監視するように指示し、それらのクラスが何であるかを調べることだけです。結果は次のとおりです。

2012-06-08 08:37:26.904 無題 2[896:707] モデルは NSObject、オブザーバーは NSObject

2012-06-08 08:37:26.907 無題 2[896:707] モデルは NSKVONotifying_NSObject、オブザーバーは NSObject

2012-06-08 08:37:26.907 無題 2[896:707] モデルは NSKVONotifying_NSObject、オブザーバーは NSObject

-classしたがって、ドキュメントが示唆するように、アプリケーション コードが合理的に期待できることを実行するのは、最初のケース (比較する場合) にすぎません。クラスを見つける他の 2 つの方法 (ランタイムに問い合わせる方法と、オブジェクト ポインターを a にキャストする方法)Class *はどちらも、KVO がクラスを下からどのように変更したかについての実装の詳細を提供します。クラスは平等です。

他の回答とコメントは と を参照しているため-isMemberOfClass:-isKindOfClass:それらの点についても説明します。

  • -isKindOfClass:クラスの平等性をテストするものではありません。がのインスタンスまたはそのサブクラスのいずれかで[object isKindOfClass: aClass]ある場合は true です。あなたが引用した文章は階級平等に関するものなので、ここでは関係ありません。とはいえ、ほとんどの場合、アプリケーション コードで実行したいのはテストです。「このオブジェクトを 「このオブジェクトは正確に ? のインスタンスですか?」よりも。objectaClass -isKindOfClass:FooFoo

  • -isMemberOfClass:はクラスが等しいかどうかのテストです。[object isMemberOfClass: aClass]オブジェクトが のインスタンスである場合にのみ真ですaClass。このテストは、-classメソッドの結果を使用して行われます。つまり、この例でmodel 、テストが陽性であることを意味し[model isMemberOfClass: [NSObject class]]ます。

于 2012-06-08T07:18:56.643 に答える
3

そのはず:

if([objctA isKindOfClass [MyClass class]])
于 2012-06-08T07:11:15.827 に答える
1

「NSStringFromClass」メソッドを使用して、「isEqualToString」のおかげで取得した文字列を比較できますか?

于 2016-09-13T06:11:58.637 に答える