2

Objective-C および XCode (4.4) の最新バージョン。

コード スニペットがあり、なぜいくつかの行を使用できるのか理解できません。説明させてください。

// For understanding purpose : (NSMutableArray*)_programStack

id l_topItemOnStack = [_programStack lastObject];
if([l_topItemOnStack isKindOfClass:[NSNumber class]])
{
    return [l_topItemOnStack doubleValue];
}

私の質問: myl_topItemOnStackは型idであり、それを a にキャストしなかったため、 .NSNumberをどのように使用できますか?[l_topItemOnStack doubleValue]

NSNumber メソッドにアクセスするには、最初に NSNumber にキャストする必要があると思いました...

ここで何が欠けていますか?

4

5 に答える 5

7

Objective-C は動的言語であるため、メッセージ名とその宣言はコンパイラのヒントにすぎません。実際のメッセージの検索と送信は実行時に行われます。したがって、コンパイラがオブジェクトがdoubleValueメッセージに応答することを認識していなくても、呼び出しを行うことができます

return objc_msgSend(l_topItemOnStack, @selector(doubleValue));

いつものように。

さらに、コンパイラは、含まれているヘッダーのどこかで宣言されているすべてのセレクターを検索し、実際のコンテキストを使用して最適な一致を見つけようとします - ここで doubleValue は一意の名前です - NSNumber でのみ宣言されているため、コンパイラーオブジェクトが確かにNSNumberです。

これを本当に回避したい場合は、メソッドを呼び出すときにオブジェクトをキャストするか、最初に NSNumber として宣言します。

于 2012-08-29T08:33:40.970 に答える
3

id任意の Objective-C クラスを表します。と同じではNSObject *ありません。その場合、最初-doubleValueにキャストしないとメソッドを使用できないためです。NSNumber

特定のクラスにキャストする必要なく、任意のメッセージをid( nilis of typeも) に送信できます。idただし、認識されないセレクターはクラッシュにつながるため、注意が必要です。

編集:
id意味:未知のクラスのObjective-Cオブジェクトへのポインタ

と の違いについて詳しく知りたい場合はid、次のブログ投稿をお読みくださいvoid *: http://unixjunkie.blogspot.de/2008/03/id-vs-nsobject-vs-id.htmlNSObject *

于 2012-08-29T08:32:20.880 に答える
3

コンパイラは、( 経由で) 翻訳に表示されるセレクターとオブジェクトを単純に一致させます#import

一致するセレクターを検索するときにあいまいさがある場合、または署名が一致せず、複数のセレクターが宣言されている場合にメッセージが表示される場合は、エラーが発生する可能性があります。その場合、オブジェクトをキャストする必要があります。

return [(NSNumber*)l_topItemOnStack doubleValue];

またはそれを新しい変数に割り当てます。

NSNumber * number = l_topItemOnStack;
return [number doubleValue];

コンパイラが適切なセレクターのシグネチャを認識できるように型を明確にするため (たとえば、スタックを正しくセットアップできるようにするため)。

MRC では、コンパイラは実際にパラメータと戻り値の型を「仮定」できます (デフォルトはid) - しかし、それは ARC では禁止されています。

于 2012-08-29T08:33:31.630 に答える
3

最初に、NSNumberがNSValueを継承するため、topItemOnStackがNSNumberのタイプであるかどうかを確認しました

NSValue オブジェクトは、単一の C または Objective-C データ項目の単純なコンテナーです。int、float、char などのスカラー型のほか、ポインター、構造体、オブジェクト ID を保持できます。

topItemOnStack can now be of any type floatValue, intValue or doubleValue as per our requirement

isKindOfClass を使用すると、topItemOnStack を NSNumber にキャストするのではなく、NSNumber 型かどうかをチェックします。

isKindOfClassは、レシーバーが特定のクラスのインスタンスであるか、そのクラスから継承する任意のクラスのインスタンスであるかを示します

于 2012-08-29T08:35:01.303 に答える
1

Objective-C オブジェクトには、実行時の型情報がバンドルされています (有名なisaポインター)。

任意のメッセージを任意のオブジェクトに送信できます。doubleValueオブジェクトがセレクター (この場合は ) に応答するかどうかを判断するためのコンパイル時の型情報が見つからない場合、コンパイラーは文句を言います (警告) id。コンパイル時に(より知識のある人がこれを確認してください)。

もちろん、id 型の変数が指すオブジェクトが対応するメソッドを実装していない場合 (つまり、送信されたメッセージに応答できない場合) は、例外がスローされます。iOS では、これはアプリケーションのクラッシュを意味します (問題のオブジェクトがこのデフォルトの動作をオーバーライドしていない限り)。OS X では、常にではありません (繰り返しますが、より知識のある人がこれを確認してください)。

于 2012-08-29T08:35:22.317 に答える