1. ホーム
  2. objective-c

[解決済み] Objective-Cでnilにメッセージを送信する

2022-11-26 01:12:57

質問

Apple の Objective-C 2.0 のドキュメントを読んでいる Java 開発者の一人として。とは何でしょうか。 nil にメッセージを送信する というのはどういう意味なのでしょうか。 ドキュメントから抜粋してみます。

Cocoaには、この事実を利用したいくつかのパターンがあります。 には、この事実を利用したいくつかのパターンがあります。そのため メッセージから nil に返される値 も有効かもしれません。

  • メソッドがオブジェクトを返す場合、任意のポインタ型、任意の整数スカラ 以下のサイズの整数スカラー sizeof(void*)以下のサイズの整数スカラー、float、double、long double、long longのいずれかを返します。 long double、long longのいずれかである。 メッセージは0を返します。
  • メソッドが構造体を返す場合、Mac OS X ABI Function Guide で定義されているように レジスタで返されるように Mac OS X ABI Function Guide で定義された構造体を返す場合 レジスタで返されるように Mac OS ABI Function Call Guide で定義されている場合、nil に送られたメッセージは に送られたメッセージは、そのデータ構造内の各フィールドに対して 0.0 を返します。 を返します。他の構造体データ タイプはゼロで埋められることはありません。
  • メソッドが前述の値以外のものを返す場合、メッセージの戻り値は を返す場合、nil に送られたメッセージの返り値は の戻り値は未定義です。

Javaは私の脳を上記の説明を理解することができないようにしたのでしょうか? あるいは、これをガラスのように明確にするために、私が見逃している何かがあるのでしょうか?

私はObjective-Cのメッセージ/レシーバのアイデアを得る、私は単にそれがたまたまであるレシーバについて混乱しています。 nil .

どのように解決するのですか?

さて、非常に巧妙な例を使って説明することができると思います。Java で ArrayList のすべての要素を出力するメソッドがあるとします。

void foo(ArrayList list)
{
    for(int i = 0; i < list.size(); ++i){
        System.out.println(list.get(i).toString());
    }
}

さて、このメソッドを次のように呼び出すと: someObject.foo(NULL); listにアクセスしようとすると、おそらくNullPointerExceptionが発生するでしょう、この場合は list.size()の呼び出しで; さて、おそらくこのようにNULL値で someObject.foo(NULL) は決して呼び出しませんでしょう。しかし、あなたは、someObject.foo(otherObject.getArrayList())のようにArrayListを生成する際に何らかのエラーが発生するとNULLを返すメソッドからArrayListを取得している可能性があります。

もちろん、このようなことをしても問題があります。

ArrayList list = NULL;
list.size();

さて、Objective-Cでは、これと同等のメソッドがあります。

- (void)foo:(NSArray*)anArray
{
    int i;
    for(i = 0; i < [anArray count]; ++i){
        NSLog(@"%@", [[anArray objectAtIndex:i] stringValue];
    }
}

ここで、以下のようなコードがあった場合。

[someObject foo:nil];

JavaがNullPointerExceptionを生成するのと同じ状況があります。nil オブジェクトは [anArray count] で最初にアクセスされます。しかし、Objective-C は NullPointerException をスローする代わりに、上記の規則に従って単に 0 を返すので、ループは実行されません。しかし、ループを一定回数実行するように設定すると、まず [anArray objectAtIndex:i] で anArray にメッセージを送っています。これも 0 を返しますが、objectAtIndex: はポインタを返し、0 へのポインタは nil/NULL なので、ループを通るたびに NSLog には nil が渡されます。(NSLogはメソッドではなく関数ですが、nilのNSStringを渡されると(null)と出力されます。

NullPointerExceptionがあったほうが、プログラムに何か問題があることがすぐにわかるので、場合によってはいいのですが、例外をキャッチしない限り、プログラムはクラッシュします。(C言語では、この方法でNULLを参照解除しようとすると、プログラムがクラッシュします。) Objective-Cでは、その代わりに、実行時に不正な動作をする可能性があるだけです。しかし、0/nil/NULL/a zeroed structを返しても壊れないメソッドがある場合、オブジェクトやパラメータがnilであることを確認する手間を省くことができます。