web-dev-qa-db-ja.com

Javaのインスタンスの置き換え?

したがって、私は現実の世界(学術プロジェクト以外)でのプログラミングにかなり慣れていないため、instanceofを使用することは、特定のオブジェクトがどのクラスであるかを判断するために使用するのは悪いことであるという多くの投稿に出くわしました。

私の状況では、3つのクラスがあります。1つは基本製品クラスで、もう1つはそれを拡張し、もう1つはそれを拡張します。これらはすべてデータベースの同じテーブルに格納されており、それぞれのメソッドを使用してデータを取得する必要があるコードがいくつかあります。

この方法で回避するためのベストプラクティスは何ですか?ポリモーフィズムについていくつか読んだことがありますが、私が抱えている問題を解決する例は見つかりません。通常、これらはすべて、異なるオブジェクトから異なるものをプルする必要があるため機能しないメソッドをオーバーライドします。

これを行うより良い方法はありますか、またはオブジェクトに固有のフィールドを取得するためにinstanceofまたはなんらかのリフレクションを使用することにこだわっていますか?

10
Thomas Mitchell

instanceofが推奨されない理由は、それがOOPではないためです。

オブジェクトの呼び出し元/ユーザーが、それがどの具象クラスのインスタンスであるかを、それが宣言されている変数のどの型を超えているかを知る必要はありません。

サブクラスで異なる動作が必要な場合は、メソッドを追加してそれらを異なる方法で実装します。

16
ratchet freak

instanceofは必ずしも悪いことではありませんが、注意する必要があります。

正しく機能する例としては、基本タイプのコレクションを取得し、サブタイプのコレクションのみが必要な場合があります。 NetworkInterface.getNetworkInterfaces()からネットワークアドレスを取得すると、InetAddressオブジェクトのコレクションを持つNetworkInterfaceオブジェクトが返されます。これらのオブジェクトには、Inet4AddressとInet6Addressがあります。 Inet4Addressオブジェクトのコレクションをフィルタリングする場合は、instanceofを使用する必要があります。

元の投稿で説明されている状況では、Baseクラスがあり、その基本クラスを拡張するものと拡張クラスを拡張するものがあります。完全に有益ではありませんが、これは理想的ではない設計の土台を持っているようです。

そのように設計された正当な理由がない限り(以前のバージョンの仕様間の後方互換性)を除き、基本クラスを返すときは、基礎となる型を調べようとすべきではありません。セットが返された場合は、セットを取得しています。これにより、開発者は後で気を変えて、より具体的なタイプ(SortedSet)を返すか、基になるタイプ(HashSetからTreeSet)を変更することができます。

オブジェクトの構造とペアレント化の設計を再検討して、型の区別を必要としない、より優れたクラスモデルを作成できるかどうかを確認します。

9
user40980

GetClass()メソッドを使用できます。

3つの異なるクラスが必要ですか?内部にスイッチがある1つのクラスのほうが良いでしょうか?

1
Gangnus

通常、何かのタイプを知りたいと思ったときは、オブジェクト構造を間違って実装したことを意味します。これらのほとんどの場合、違反 [〜#〜] lsp [〜#〜] になります。

ただし、動的ディスパッチを実行して大量のボイラープレートコードを保存し、オブジェクト構造の将来性を保証する方法が欲しい場合があります。 C#はフレームワークの新しい分割払いで動的キーワードを提供しますが、私の知る限り、Javaにはまだ似たようなものはありません。

とは言っても、instanceofは継承を適切にサポートするため、クラスを比較するよりも一般的に優れています。 isAssignableFromなどのメソッドをリフレクションAPIから使用することもできます。動的ディスパッチなどを実装したい場合は、リフレクションAPIを介して実行できますが、注意が必要です。注意して使用してください。可能であれば、オブジェクト構造とアプリのデザインを修正するのが理想的です。

お役に立てれば

1
Newtopian