3

実際、私は Java のバックグラウンドを持っており、Objective C を学習しています。Objective C の奇妙な動作について非常に混乱しています。

質問は順番に提供されますので、私や他の人が理解できるように順番に答えてください。

質問 1 :と:
から派生した 2 つのクラスがあります。NSObjectAB

@interface A : NSObject 
@end                               

@interface B : NSobject
-(void)display; // It displays "I am class B"
@end

今私がこれを行うと:

A *a = [[B alloc]init]; // Show warning not error (it must be illegal)
[a display];            // prints "I am class B"

クラス B の表示メソッドを呼び出します。

  1. Aメソッドがありませんdisplay。ポリモーフィズムによる。

  2. これは、任意のクラスの参照を作成し、別のクラスのオブジェクトを渡し、それによってデータにアクセスしているため、セキュリティ上の脅威になる可能性があります。

  3. Dogクラス インスタンスがクラスのオブジェクトを取得し、インスタンスでメソッドをPrinter呼び出しているため、設計上の問題が発生する可能性があります。printDog

  4. の参照NSArrayと渡されたオブジェクトがあり、現在、このインスタンスでメソッドをNSMutableArray呼び出しています。NSMutableArray

    [nsarri addObject:@:abc]; //非常に奇妙に見える

質問 2
プロトコル がFooあり、それを確認していないクラスはありますか。プロトコル参照でそのクラスのオブジェクトを取得することは許可されるべきではありません。

@protocol Foo
@required
-(void)abc;
@end    

私が電話した場合:

id<Foo> obj= [[B alloc]init]; // Shows warning ignore it for now as it must be illegal also
[obj display];                // It will call display method which should be illegal  
  1. プロトコルにB準拠しておらず、オブジェクトを取得してインスタンスメソッドを呼び出しているため、発生しないはずです。ポリモーフィズムとセキュリティのために非常に悪いと思いますFooobjBB

質問 3
クラスに、自動解放されていないそのクラスのオブジェクトを返すクラス メソッドがある場合、コンパイラは警告を表示します。そのクラス(プロトコルに準拠していない)メソッドから返されたオブジェクトをプロトコルの参照に渡すと。(それはエラーであるべきです)。

id<Foo> obj = [Abc aClassMethodReturnsObjectWhichNotAutoreleased]; //show warning

それは良い警告を示しています。 Abcプロトコルに準拠していませんでしたFoo

しかし

id<Foo> obj = [NSArray arrayWithObjects:@"abc",@"def",nil]; // It does **not** show a warning as it will return autorelease object. NSArray doesn't conform protocol Foo

NSArray前の例に示されているように、クラス への上記の割り当てで警告が表示されないのはなぜですか。

前もって感謝します。

編集

* 3 番目の質問への回答: *NSArray は "id obj" を渡すことを許可する id オブジェクトを返しますが、"aClassMethodReturnsObjectWhichNotAutoreleased" の場合、メソッドは "ABC *" ポインターを返すため、この場合コンパイラは警告を出します。

4

3 に答える 3

2

あなたが発見したように、Objective-C と Java には非常に異なる型規則があります。

Java は厳密に静的に型指定されています。つまり、型が一致する必要があり、型変換規則で許可されていない割り当てを行うことはできません。

Objective-C は、オプションの static typesを使用して動的に型付けされます。いつでも型システムから抜け出すことができます。場合によっては、コンパイラが警告を発しますが、それでも許容されます。

これが、この動作が見られる理由です。Objective-C は壊れていません。Java で知っているルールとは異なるルールを持っているだけです。

Apple には、特定のルールに関するドキュメントが多数あります。おそらく、Enable Static Behaviorを参照してください。

動的型付けと静的型付けに関するその他のリソースを次に示します。

動的型言語と静的型言語の比較および動的言語の何が魅力的なのか?

于 2012-11-10T14:48:31.560 に答える
2

質問1:

A *a = [[B alloc]init]; //Show warning not error (it must be illegal)
[a display];  //prints "I am class B"

Aここでは、 という名前の変数に静的型を使用していますa。次に、別のタイプのオブジェクト ( B) を変数に割り当てます。

Java とは異なり、Objective-C は静的型付けの要件を強制しませんが、オブジェクトの宣言された型と実際の型の違いをコンパイラが検出したため、コンパイル時に警告を発します。ただし、喜んで B オブジェクトを変数に詰め込んでいるので、作成aしたオブジェクトを指していBます。プログラムがコンパイルされて実行されると (実行時)、A *aは と同じように扱われid aます。

Objective-C のもう 1 つの機能は、任意のメッセージを任意のオブジェクトにいつでも送信できることです。これは、Objective-C の動的な性質の一部です。明らかに、間違ったメッセージをオブジェクトに送信すると悪いこと(tm) が発生する場合があるため、適切なメッセージのみを送信するようにする必要があります。実行時にオブジェクトのクラスをテストしたり、悪いことを防ぐために特定のメッセージを送信する前に処理できるかどうかをテストしたりできるさまざまな関数があります。静的型付けを使用している場合 (この例のように)、コンパイラは警告を発行して、間違いを犯した可能性があり、コードを確認する必要があることを通知します。

質問2:

これは実際には質問 1 と非常によく似ています。コンパイラは、変数に誤った値と思われるものを割り当てていることを警告していますが、実行時に任意のメッセージを任意のオブジェクトに送信できるため、実際の型宣言からの「期待される」オブジェクトの代わりにオブジェクト。

質問 3:

良い質問。そこにも警告が表示されると思っていました。たぶん、他の誰かがそれを手伝ってくれるでしょう。私の最初の考えは、これはバグであり、そのように報告されるべきであるということですが、私が気付いていない理由があるかもしれません....

于 2012-11-10T15:58:14.800 に答える
1
A *a = [[B alloc]init]; //Show warning not error (it must be illegal)
[a display];  //prints "I am class B"

表示プロパティを持つ B クラスから変数を初期化したためです。あたりです

于 2012-11-10T14:48:11.390 に答える