質問

今日、奇妙な問題に出会いました。 UIViewのサブクラスを作成し、xcodeが提供するテンプレートコードにメソッドを1つだけ追加しました。

@interface FloatView : UIView {

}
- (void)floatTest:(CGFloat)x;
@end

- (void)floatTest:(CGFloat)x {
  NSLog(@"float was %f", x);
}

その後、appDelegateに次のようなコードがありました:

UIView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];

非常に簡単ですよね?これは何を印刷すべきですか? 「10.0000」のようなものになると思いましたが、「0.000000」と印刷されます。

何時間もこれに取り組んで、何が間違っていたかを把握しようとしてから、appDelegateのコードを

に変更しました
FloatView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];

その後のみ、予想される「10.0000」を印刷しました。これはなぜですか? FloatViewをUIViewのサブクラスとして宣言しましたが、FloatViewオブジェクトをUIViewポインターに問題なく割り当てることはできませんか?

floatViewがUIViewへのポインタとして宣言されていたとしても、それは実際にはfloatViewであり、floatTestメッセージを処理できるはずですか?私はここで完全に離れていますか?

役に立ちましたか?

解決

実際、ポリモーフィズムは期待どおりに機能しています。動作しなかった場合、何も印刷されませんでした(例では、0.0000が印刷されています)。問題は、インスタンスが実際に testFloat:10.0f メッセージに応答する一方で、コンパイラがメソッド宣言を静的に見ることができないためです( UIView クラスはメソッド)、メソッドが引数として ... を取り、 id を返すと仮定します。

CGFloat が可変数の引数( ... )を必要とするメソッドに渡されると、 double に昇格されます。したがって、受信メソッドには double 引数が渡され、 float であると見なされ、正しく印刷されません。

NSLog 行を次のように変更することにより、この動作を確認できます。

NSLog(@"%f", *(double*)&x);

コンパイラが UIView * ではなく FloatView * にメッセージを送信すると、メソッドの正確なシグネチャを見つけることができます。本当に CGFloat を期待し、引数を double に昇格させないことがわかります。その結果、正常に機能します。

さらに、 UIView * CGFloat をとるメソッド宣言が含まれている場合、コンパイラはメソッドを適切に呼び出します。要約すると、これはポリモーフィズムの問題ではありません。メソッド署名の問題がありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top