4

少し困惑していることを見つけたところです。どなたか親切に説明していただけないでしょうか。

NSArray *nextArray = [NSArray arrayWithObjects:@"ONE", @"TWO", @"THREE", nil];
for(id eachObject in nextArray) {
    NSLog(@"COUNT: %d", [eachObject length]);
}

IDの長さを要求しているという事実について、上記が不平/警告を出さないのはなぜですか?

4

6 に答える 6

5

Objective-Cidでは、クラスに関係なくあらゆる種類のオブジェクトの一般的な型であり、クラスのインスタンスおよびクラス オブジェクト自体に使用できます。このid型は完全に非制限的であり、それがオブジェクトであることを除いて、オブジェクトに関する情報はありません。そのため、コンパイラーは、そのオブジェクトがメソッドに応答できるかどうかを知る方法がありません。コンパイラーは、それがどのようなオブジェクトであるかを認識していないためです。あなたのコードでそれを使用することで、基本的に「これが指しているものが何であれ、この操作を実行する」と言っていることになります。

于 2012-08-01T16:57:10.730 に答える
4

コンパイラは、id に送信された型チェック メッセージを決してタイプしません。それが、Objective-C のダイナミズムを可能にしている理由の 1 つです。

eachObject が他の型の場合、コンパイラがメソッド名を解決できなかった場合にエラーが発生します。

于 2012-08-01T16:52:25.447 に答える
4

idコンパイラの型チェックが特に必要ない場合に使用します。警告なしで型に任意のメッセージを送信でき、型キャストなしで他の型に をid割り当てることができます。id

これにより、キャストを使用せずに配列からオブジェクトを取得できます。たとえば、配列に NSString が含まれていると自由に想定できます。

NSString* someString = [myArray objectAtIndex:1];

また、キャストや警告なしでオブジェクトにメッセージを送信することもできます。実際、送信したいメッセージは、正式なクラスまたはプロトコルの一部ではない場合があります。

id someObject = [myArray objectAtIndex:1];
if ([someObject respondsToSelector:@selector(setName:)])
{
    [someObject setName:@"Foo"];
}
于 2012-08-01T17:00:54.550 に答える
3

には、次のNSArrayようなさまざまなオブジェクト タイプが含まれる場合があります。

NSArray *thArray = [[NSArray alloc] initWithObjects:@"Stack",@"Overflow",[NSNumber numberWithInt:10],nil];
for(id theObject in thArray) {
    NSLog(@"COUNT: %lu", [theObject length]);
}

id任意のオブジェクト (この場合はNSStringまたはNSNumber)を表すことが
できるため、コンパイラはプリミティブ メソッドlengthが存在するかどうかを知ることができません。

于 2012-08-01T16:57:24.630 に答える
1

簡単に言うと、id はすべての Objective-C クラスを意味します。したがって、length メソッドは NSString クラスに属します。コンパイラは警告をスローしません。id は実行時に動的に決定され、コンパイル時には不明です。

于 2012-08-01T16:56:09.917 に答える
0

Objective-C の各オブジェクトは、それが持つクラスと、メッセージを処理できるかどうかを認識しています。クラスをチェックするのはコンパイラではなく、実行時のオブジェクトそのものです。

オブジェクトのクラスはコンパイラ時に未定義になる可能性がありますが、実行時には各オブジェクトに定義済みのクラスがあります。

于 2012-08-01T16:54:07.817 に答える