4

今日、Objective-C コンパイラが許可するとは思わなかった奇妙な動作に遭遇しました。

UITableViewCell には、UIImageView 型の imageView という名前のプロパティがあります。UITableViewCell をサブクラス化し、imageView を上書きしましたが、AWImageView は UIImageView のサブクラスであるタイプ AWImageView で作成しました。コンパイルされないと思っていましたが、コンパイルされます。すべてがうまく機能します。私はその行動に非常にショックを受けました。

サブクラスのプロパティのタイプを絞り込むことは正式に許可されていますか? それとも、これを機能させた Objective-C コンパイラのバグですか?

4

2 に答える 2

5

これを行うことが許可されているというあなたの疑いには十分な根拠がありますが、この特定のケースでは大丈夫です...

オーバーライドの厳密なサブタイプ解釈では、オーバーライド メソッドは、より一般的な型の引数を受け入れ、より具体的な型の値を返す場合があります。

たとえば、Objective-C を使用すると、次のようになります。

@interface A : NSObject { ... }
@interface B : A { ... }
@interface C : B { ... }

BのメソッドM:

- (B *) M:(B *)arg { ... }

次に、厳密なサブタイプの下のクラス C では、次を使用してクラス C でこれをオーバーライドできます。

- (C *) M:(A *)arg { ... }

明らかに B オブジェクトへの参照がある場合、これは安全です。

B *bObj = ...;

次に、メソッド M が次のように呼び出されます。

B *anotherBObj = [bObj M:[B new]];

次に、bObj実際に B か C かは、呼び出しの型が正しいことです。C オブジェクトの場合、B である引数は A でもあるので問題なく、C である結果も B であるため問題ありません。

これにより、完全ではありませんが、あなたの財産につながります。Objective-C では、プロパティは 2 つのメソッドの省略形にすぎません。

@property B *myBvalue;

は次の省略形です。

- (void) setMyBvalue:(B *)value;
- (B *) myBvalue;

そのプロパティが B で宣言され、C 値のプロパティを使用してクラス C でオーバーライドする場合:

@property C *myBvalue;

あなたが得る:

- (void) setMyBvalue:(C *)value;
- (C *) myBvalue;

メソッドsetMyBvalue:は厳密なサブタイピング ルールに違反しています。C インスタンスを B インスタンスにキャストすると、型付けルールでは B を渡すことができ、メソッドは C を期待し、混乱が生じる可能性があります。

ただし、あなたの場合、オーバーライドしているプロパティはreadonlyであるため、セッターも危険もありません。

于 2012-05-23T04:44:22.080 に答える
1

AWImageView が UIImageView から派生 (サブクラス) している場合、それは UIImageView であるため、コンパイラにとってはすべて同じままです。

ドキュメントから:

ここに画像の説明を入力

Figure 1-1 […] これは単純に、Square 型のオブジェクトは正方形であるだけでなく、長方形、形状、グラフィック、および NSObject 型のオブジェクトでもあるということです。

于 2012-05-23T00:05:43.210 に答える