(私がもっと抽象化X
し、それに別のメソッドを追加する必要があることをアドバイスしないでください。)
C ++では、型の変数x
があり、それが型(のサブクラス)X*
でもある場合に特定のことを実行したい場合、次のように記述します。Y*
Y
X
if(Y* y = dynamic_cast<Y*>(x)) {
// now do sth with y
}
同じことはJavaでは不可能のようです(またはそうですか?)。
代わりに、このJavaコードを読みました。
if(x instanceof Y) {
Y y = (Y) x;
// ...
}
変数x
がなくても、より複雑な式である場合は、この問題のために、Javaでダミー変数が必要になることがあります。
X x = something();
if(x instanceof Y) {
Y y = (Y) x;
// ...
}
// x not needed here anymore
(一般的なことはそれsomething()
ですiterator.next()
。そして、それを2回だけ呼び出すこともできないことがわかります。本当にダミー変数が必要です。)
ここでは実際にはまったく必要ありません。キャストで一度にチェックをx
行うことができないため、必要なだけです。instanceof
これを、非常に一般的なC++コードともう一度比較してください。
if(Y* y = dynamic_cast<Y*>( something() )) {
// ...
}
castOrNull
そのため、ダミー変数を回避できる関数を導入しましたx
。私は今これを書くことができます:
Y y = castOrNull( something(), Y.class );
if(y != null) {
// ...
}
の実装castOrNull
:
public static <T> T castOrNull(Object obj, Class<T> clazz) {
try {
return clazz.cast(obj);
} catch (ClassCastException exc) {
return null;
}
}
さて、このcastOrNull
関数をそのように使うのは悪いことだと言われました。何故ですか?(または、より一般的な質問になります。同意し、これも悪だと思いますか?はいの場合、なぜそうですか?または、これは有効な(おそらくまれな)ユースケースだと思いますか?)
言ったように、私はそのようなダウンキャストの使用がまったく良い考えであるかどうかについて議論したくありません。しかし、なぜ私が時々それを使用するのかを簡単に明らかにしましょう:
時々、非常に特定の事柄に対して別の新しいメソッドを追加するか(1つの特定の場合に1つのサブクラスにのみ適用される)、そのような
instanceof
チェックを使用するかを選択する必要がある場合があります。基本的に、関数を追加するか、チェックdoSomethingVeryVerySpecificIfIAmY()
を行うかを選択できます。instanceof
そしてそのような場合、後者の方がきれいだと思います。時々私はいくつかのインターフェース/基本クラスのコレクションを持っていて、タイプのすべてのエントリーについて
Y
、何かをしてからそれらをコレクションから削除したいと思っています。(たとえば、ツリー構造があり、空の葉であるすべての子を削除したい場合がありました。)