1

次のように、オブジェクトの実際のタイプを使用して、使用するメソッドを定義できることを学びました。

[...]
Object foo = new String("hello");
[...]
bla(foo);

void bla(String x){
}
void bla(Integer x){
}

これでメソッドを使用する必要がありますbla(String x)が、代わりにコンパイラエラーが発生します。私は理由を知っています:タイプfooが現在であるためObject。現在正しく行っているかどうかはわかりませんが、Javaは実際のタイプ(または特定のタイプ)でメソッドを選択するので、ダウンキャストすると代わりにObject選択されます。メソッドが指定されています。StringObject

または、メソッドでタイプを判別する唯一if(foo instanceof xxx)の方法ですvoid bla(Object x)?

PS:これについて誤解しないでください:メソッドをオーバーロードできるという意味ではありません。つまり、(定義されたタイプではなく)実際のタイプに基づいてメソッドを選択したいということです。

4

2 に答える 2

1

これでb​​la(String x)メソッドを使用する必要がありますが、代わりにコンパイラエラーが発生します。

右。実行時に呼び出されるメソッドはコンパイル時に選択され、コンパイラは(一般に)実行時にどのタイプfooが使用されるかを判断できません。

...オブジェクトにダウンキャストした場合...

「オブジェクトにダウンキャスト」することはできません。あなたはしかしにダウンキャストすることができStringます。そうです、もしあなたがそうするなら

bla((String) foo);

bla引数としてaをとるを呼び出します(そして、そうでない場合はifStringをスローします)。ClassCastExceptionfooString

または、メソッドvoid bla(Object x)のif(foo instanceof xxx)によってタイプを判別する唯一の方法ですか?

[...]

つまり、(定義されたタイプではなく)実際のタイプに基づいてメソッドを選択したいということです!

これは通常、ダブルディスパッチまたはマルチディスパッチと呼ばれ、Javaではサポートされていない機能です。

本当に必要な場合は、ビジターパターンを実装してください。


ところで、あなたが「定義されたタイプ」と「実際のタイプ」と呼ぶものは、通常、それぞれ静的タイプランタイムタイプと呼ばれます。つまり、Objectはの静的タイプでありfooString実行時タイプです。

于 2011-10-10T08:06:25.757 に答える
0

ええ、あなたはinstanceof本当にタイプを取得するために使用する必要があります。bla(Object)は常にbla(Object o)メソッドを呼び出します。

注:「実数型」に基づくメソッドの選択は、クラスメソッドでのみ可能です。object.method(...)。「実際のタイプ」が存在する場合はそれに基づいてメソッドを選択します(そしてオブジェクトまで上昇します)。

Object foo = new String("hello");

// this will return "hello" although toString() 
// from Object only prints the reference
System.out.println( foo.toString() );
于 2011-10-10T08:06:13.783 に答える