2017-01-17 6 views
0

私は、一番上の親クラスを変数型として使用して子インスタンスを保持し、一部の人は親クラスのみを使用する人を見てきました。例:一番上の親クラスを参照変数の型として使うべきですか?

Collection obj = new ArrayList(); 
Or 
List obj = new ArrayList(); 

ここで、ListはCollectionの下にあり、次に2番目ではなく1番目の行を使用できませんか?

ここでも、CollectionフレームワークでCollectionクラスの参照変数は、Collectionの下にあるクラスのインスタンスを保持するためだけに使用できません。

これは良い方法ですか?

だから、ベストプラクティスの下にあるのはなぜですか、なぜですか?

誰かが技術的にパフォーマンスの懸念などを正当化する可能性があれば、大いに感謝します。

答えて

2

一般的な考え方は可能な限り隠れているため、変更が容易です。たとえば、インデックス作成が必要な場合(List.get(int index))、コレクションは.get(index)をサポートしていないため、リストでなければなりません。インデックスを作成する必要がない場合は、リストを使用しているという事実を隠す

たとえば、おそらく1ヵ月後にリストの代わりにセットを使用したいと思いますが、Setは.get(index)をサポートしていません。このリストを使用する人は、リストのインデックス機能を使用する可能性があり、他の誰かが.get()を使用した場所が破損するため、セットに切り替えるのが難しくなります。

一方、タイプを過度に隠すと、メソッドのコンシューマが型を知らなかったため、偶然のパフォーマンスの問題を引き起こす可能性があります。 atは実際にはリンクされたリストです(インデックスはO(n)です)。このリストのコンシューマが別のリストの各エントリを参照するとします。これは、実際に遅いO(n * m)のパフォーマンスになります。最初にリンクリストであることを宣伝した場合、リンクリストの消費者は、このリストに複数のインデックスを作成し、消費者がローカルコピーを作成することはおそらく良い考えではないことを認識します。

ライブラリのコード(あなたが設計しているものを想定)

public class Util { 
    public static List<String> makeData() { 
    return new LinkedList(Arrays.asList("dogs", "cats", "zebras", "deer")); 
    } 
} 

発信者のコード(ライブラリまたはメソッドを使用しています1を想定)

public static void main(String [] args) { 
    List<String> data = Util.makeData(); 
    int [] indicesToLookUp = {1,4,2,3,0}; 
    for(int idx : indicesToLookUp) { 
    if(idx < data.size()) { 
     // each index (LinkedList.get()) is slow O(N) 
     doSomethingWithEntry(idx, list.get(idx)); 
    } 
    } 
} 

あなたはそれがあるため、呼び出し側のせいだと主張できました彼は誤ってリストがArrayList <>であると仮定し、リストのローカルコピーを作成しておく必要がありました。

+0

これはとても良い答えすることができ、私はあなたの一票を上にあげます。しかし、私はあなたが "それは本当に遅いO(n * m)のパフォーマンスになることができる"と言及した最後のパラの意味を理解できませんでした。あなたはもっと良い方法でそれを理解するために私にそれに関する良い参考文献を教えていただけますか? – Joy

+0

私の開発の逸話であるので、私はそれのためのリファレンスを持っていません。私は例を追加しようとします。私は最初の2つの段落についてもっと詳しく知っています:http://softwareengineering.stackexchange.com/questions/132019/what-is-the-value-in-hiding-the-details-through-abstractions-isnt-there-value 。彼らは私がしたよりもはるかに優れた仕事をしています。 – joseph

2

本当にあなたのニーズにかかっています。あなたの例では基本的なニーズにはそれほど変化はありませんが、2つのインターフェースを調べるといくつかの変更があります。見て: https://docs.oracle.com/javase/7/docs/api/java/util/Collection.htmlhttps://docs.oracle.com/javase/7/docs/api/java/util/List.html

を我々はリストには、コレクションにはないメソッドにアクセスすることができますことに気づくことができます。
set(int index、E element)は、Listインタフェースで定義されており、Collectionでは定義されていません。

これは、Collectionを継承するすべてのクラスがすべて同じメソッドを実装する必要がないためです。

パフォーマンスには影響ありません。

必要なすべての機能を備えた最上位の親クラスを常に使用してください。あなたの例では、Listより上に行く必要はありません。

2

参照型に使用するクラスを選択するためのいわゆる「ベストプラクティス」はありません。実際、最上位階層のクラスはObjectクラスです。あなたはあなたがやっているすべてのものの参照型としてObjectを使用していますか?いいえ、一般的には、あなたのニーズに合ったすべての方法で上級クラスを選ぶことができます。

いわゆる「ベストプラクティス」の代わりに、自分の状況に適したものを適用してください。

これらは、参照型として上位階層のクラスを使用するためのいくつかの長所と短所である:

アドバンテージ

  • は同じ祖先を共有するオブジェクトのグループ化(スーパークラス)
  • が許容でき指定されたクラスのすべてのインスタンスが割り当てられます。

    Animal dog = new Dog(); 
    Animal cat = new Cat(); 
    
  • あなたは共通行動やメンバーにアクセスしているとき、それは唯一の利点である多型

    dog.makeNoise(); 
    cat.makeNoise(); 
    

ことができます。あなたは一つのオブジェクトには存在しますが、他のない行動をアクセスしているとき

  • 欠点は、鋳造が必要です。あなたが共通の親クラス内のさまざまなオブジェクトをダンプを開始したよう

    dog.swim(); //error, class Animal do not have swim() 
    ((Dog)dog).swim(); 
    
  • は、あなたがどのクラスに属するメンバーを把握しよう苦労を有することができます。

    (Cat(cat)).swim(); //error, class Cat do not have swim() 
    
関連する問題