1

Objective-C のクラス継承に関連する奇妙なシナリオに遭遇しました。

基本クラス X から継承する 3 つのクラス A、B、および C があるとします。クラス A、B、および X にはコンストラクターがあります。

- (id)InitWithString:(NSString*)someString andDelegate:(id<SomeProtocol>)aDelegate

唯一の違いは、すべてのクラスがデリゲートに異なるプロトコルを使用することです。

A と B に対して、コンパイラは C のメソッドを使用しようとします。警告は、クラス C のコンストラクターが必要とするプロトコルが提供されたデリゲートによって実装されていないことを通知します。各クラスには、クラス独自のコンストラクターに適切なプロトコルを実装するデリゲートがあるため、デリゲート自体に問題はありません。実行時にはすべてが正常に機能し、すべてのクラスに対して適切な関数が呼び出されます。

コンストラクターが匿名 ID の代わりに A*、B*、または C* を返すようにしてみましたが、それでも問題は解決しません。

機能する唯一のことは、次のように適切なクラスにキャストすることです。

instanceOfA = [(A*)[A alloc] InitWithString:@"" andDelegate:aDelegate];

これは余分で不必要に思えます。私はおそらくここで明らかな何かを見逃しています。

4

2 に答える 2

1

これらのケースでアナライザーが実際にどれほど賢いかはわかりませんが、単にその限界の 1 つにぶつかっただけだと思います。

あなたが観察しているのは、オブジェクトを見てid、署名に一致する最初のメソッドを選択するコンパイラです。クラスを含める順序を移動してみてください。最初に定義されたセレクターが常に選択されることがわかります。

これを回避する方法は、2 つのステップでクラスを初期化することです。

ClassA *test = [ClassA alloc];
test = [test initWithString:@"" andDelegate:delegate];

この場合、アナライザーはテストのタイプが ClassA であることを認識し、正しいセレクターを選択します。変数に代入されず、常にid.

于 2009-12-16T15:37:17.163 に答える
1

問題は、指定された型のパラメーターを定義するメソッドの宣言にあります。

最後のパラメーターとして渡されたオブジェクトのすべてのクラスに対して有効になるように、宣言をできるだけ汎用的にする必要があります。すべてのプロトコルが親プロトコルから継承する場合、メソッドを次のように宣言できます- (id)initWithString:(NSString*)someString andDelegate:(id<ParentProtocol>)aDelegate。別の方法として、より一般的な定義を使用できます- (id)initWithString:(NSString*)someString andDelegate:(id)aDelegate

于 2009-12-16T15:27:19.067 に答える