web-dev-qa-db-ja.com

instanceofは悪い習慣と見なされていますか?その場合、instanceofはどのような状況でもなお望ましいですか?

長年にわたり、可能な限りinstanceofを避けようとしました。該当する場合、ポリモーフィズムまたは訪問者パターンを使用します。状況によっては簡単にメンテナンスが簡単になると思います...他に注意すべき欠点はありますか?

しかし、私はJavaライブラリでそれをあちこちで見るので、私はそれがその場所を持っていると思いますか?

62
aioobe

いくつかのケースを想像できます。たとえば、ライブラリのいくつかのオブジェクトを拡張することはできません(拡張するのは不便です)。コレクション。
そのような場合、instanceofを使用してこれらのオブジェクトの処理を区別すると便利だと思います。

新しい小さな機能やバグ修正を追加するためだけに、多くの古いクラスに新しい動作を挿入できないレガシーコードのメンテナンスを確認してください...

11
PhiLho

equalsのストック実装で間違いなくその場所を持っています。例えば。

public boolean equals ( Object o )
{
  if ( this == o )
  {
     return true;
  }

  if ( ! (o instanceof MyClass) )
  {
    return false;
  }

  // Compare fields
  ...
}

Instanceofについて知っておくべき1つのすてきなことは、そのLHSがnullになる可能性があることです。その場合、式はfalseに評価されます。

22

オブジェクトのタイプを絶対に知る必要がある場合、instanceofが最良の選択肢です。

悪い習慣は、たくさんのinstanceofsを隣同士に並べて、それらに応じてオブジェクトの異なるメソッドを呼び出すことです(もちろんキャスト)。これはおそらく、階層を再考し、おそらくリファクタリングする必要があることを反映しています。

13
Daniel Dolz

純粋なOOモデルの場合、instanceofは間違いなくコードの匂いです。

ただし、100%OOモデルを使用していない場合、または外部からモデルにデータを注入する必要がある場合は、instanceofまたは同等の(isXXX()getType()、...)を使用できます。

一般的な「ルール」は、特にyoタイプ階層を制御し、たとえばサブタイプ多態性を使用できる場合に、可能な限り回避することです。目的は、オブジェクトのタイプを尋ねて何かをするのではなく、ビジター(本質的に二重ポリモーフィズム)を介してオブジェクトに直接または間接的に問い合わせて何らかのアクションを実行することです。

5
eljenso

悪臭を放つことに同意します。大量のinstanceofは、特にブロックされた場合は連鎖して、悪臭がします。

時々、あなたが予期しないような振る舞いをすることがあります...私が一度起こったこと:

Class B extends A
Class C extends A

B b = new B();
C c = new C();

b instanceof B -> true
b instanceof C -> true
c instanceof C -> true
c instanceof B -> true

(私の場合、これはプロキシオブジェクトを作成する休止状態のために発生しました。

2
bwawok

キャスト前の健全性チェックとして使用できます。オブジェクトが正しい型であることを確認することに加えて、それがnullでないことも確認します。

if (o instanceof MyThing) {
    ((MyThing) o).doSomething(); // This is now guaranteed to work.
} else {
    // Do something else, but don't crash onto ClassCast- or NullPointerException.
}
1
Joonas Pulakka

作成工場の場合はどうですか?例えば.

public static Cage createCage(Animal animal) {
  if (animal instanceof Dog)
    return new DogHouse();
  else if (animal instanceof Lion)
    return new SteelCage();
  else if (animal instanceof Chicken)
    return new ChickenWiredCage();
  else if (animal instanceof AlienPreditor)
    return new ForceFieldCage();
  ...
  else
    return new GenericCage();
}
0
Thor