2016-12-08 13 views
0

以下の段落は、Bruce Eckelの "Thinking in Java"という本から引用されています。Javaの継承を超える合成の利点

構成には多大な柔軟性があります。新しいクラスのメンバオブジェクトは通常プライベートなので、クラスを使用しているクライアントプログラマはアクセスできません。これにより、既存のクライアントコードを妨げずにメンバーを変更することができます。 実行時にメンバオブジェクトを変更して、プログラムの動作を動的に変更することもできます。次に説明する継承では、継承がで作成されたクラスに対してコンパイラがコンパイル時の制限を設定する必要があるため、この柔軟性はありません。

メンバーオブジェクトを動的に変更する方法、および継承を上回る利点についてはわかりません。 誰か説明してください

+1

メンバオブジェクトは参照フィールドから利用でき、それらが変更可能な場合は、割り当てを使用して変更することができます。すなわち、 '=' –

+0

コード例を教えてください。 –

+0

なぜdownvoteですか? –

答えて

6

クラスがArrayListの場合、クラスのユーザーはArrayListのすべてのパブリックメソッドにアクセスできます。 LinkedListを拡張するためにクラスを変更することはできません。既存のコードが破損する可能性があるからです。

public class Inheritence extends ArrayList<String> 
{ 
    // here your class depends on ArrayList implementation 
} 

、一方で、あなたのクラスは、型がListあるプライベートメンバを持っている場合は、あなたのクラスのユーザーが直接そのメンバーのメソッドを呼び出すことはできません。実行時にArrayListインスタンスをそのメンバに割り当てるか、異なるListの実装(LinkedListまたは他のもの)を割り当てるかを決定できます。

public class Composition 
{ 
    private List<String> member; 

    public Composition() 
    { 
     // here you decide the type of your member during runtime 
     if (someCondition) { 
      member = new ArrayList<String>(); 
     } else { 
      member = new LinkedList<String>(); 
     } 
    } 
} 
1

継承を使用する場合は、ほとんど全体像を見ていない、あなたは多くが起こっているのかを理解できるようにするには、コードの地獄を勉強しなければなりません。あなたが親クラスで小柄なものを変更した場合、あなたは問題を抱えています。すべての子孫はどうですか?この変更がそれらに影響しましたか?

また、テストを検討してください。親クラスは分離できません。すべてをテストしなければならず、テストは複雑であり、しばしば全く行われません。

一方、合成を使用すると、簡単に機能を分離したり、依存性注入を使用したりすることができます。他の人のコードを読むときは、小さな機能に集中できます。コンポジションを使用する上位レベルのクラスが、他の実装で若干の機能を置き換える必要がある場合は、コード内で何が起こっているかをはるかによく知っているので、はるかに簡単です。いくつかのレベルの継承の分散コードはカプセル化されておらず、非常にしばしば完全に読めません。

継承も危険です。たとえば、カウントしたい場合、HashSetに追加したアイテムの数を仮定します。メソッドaddとaddAllをオーバーライドすることはできますが、addAllがメソッドaddをすべての項目に対して呼び出すかどうかはわかりません。これを参照してくださいexample

元の質問に答えるには - コンストラクタまたはセッターで内部オブジェクトを渡すことができます。

2

組成と継承を見ての広い方法は、組成物は、継承がis-a関係を実現する技術であるのに対し、has-a関係を実装するための設計手法です。これをより良い方法で理解するために、オブジェクト指向の視点に移りましょう。私が言う

DogMammalSnakeReptileであるが、両方が、デザインは、のようにすることができますと呼ばれるスーパークラスがあるはずAnimalsされているMammalReptileDog呼ばAnimalと2つのクラスSnakeを拡張する必要があります。それぞれのコードは次のとおりです。

public abstract class Animal { 
    public abstract void move(); 
    public abstract void sleep(); 
    public abstract void reproduce(); 

} 

これらの3つのアクションは、どの動物でも実行できます。

public abstract class Mammal extends Animal{ 
    @Override 
    public void reproduce(){ 
     System.out.println("Gives birth!!"); 
    } 

} 

public abstract class Reptile extends Animal{ 
    @Override 
    public void reproduce(){ 
     System.out.println("Lays Eggs!!"); 
    } 
} 

すべての哺乳類/爬虫類は、共通の方法でこの定義された機能を実行します。この例で観察することができたよう

public class Dog extends Mammal{ 

    @Override 
    public void move() { 
     System.out.println("Uses it's limbs"); 

    } 

    @Override 
    public void sleep() { 
     System.out.println("Sleeps on it's tummy"); 

    } 

} 


public class Snake extends Reptile{ 

    @Override 
    public void move() { 
     System.out.println("Crawls"); 

    } 

    @Override 
    public void sleep() { 
     System.out.println(""); 

    } 

} 

DogMammalSnakeReptileを拡張を拡張します。したがって、時間の任意の時点で、Dogは常になりMammalSnakeは常にReptileあろう。したがって、このは-の関係は、強い債券を2つのエンティティの間に構築します。実行の過程で、DogMammalに拡張されている限り、Reptileまたはそれ以外のものにすることはできません。 に戻ってくることは関係(作曲)、持っている

のに対し、私はPersonは、持っているCarと言うことができます。この人が持っているCarの種類を指定していません。これをよりよく理解するために、オブジェクト指向の視点に戻ってみましょう。

このPersonクラス

public class Person { 
    private String name; 
    private String address; 

    private Car car; 

    public Person(String name, String address, Car car) { 
     super(); 
     this.name = name; 
     this.address = address; 
     this.car = car; 
    } 


} 

考えてみましょうPersonがあり-、という名前、住所、車をここで見ることができます。 車および関連するクラスのコードは以下の行く:

public class Car { 
    //Car related methods 
} 

public class Ferrari extends Car{ 
    //Ferrari specific methods, attributes 
} 

public class Bmw extends Car{ 
    //BMW specific attributes, methods. 
} 

BMWFerrariCarのタイプであることがわかります。 「Person has-a Car」のステートメントに戻ると、その車はどの車でもかまいません。それはフェラーリかBMWか何か他のものかもしれません。これはPersonオブジェクトの作成中に渡すことができます。

Person john = new Person("John", "#81, 2nd Street,..", new Ferrari());

ジョンがFerrariCarにとることがわかります。ここでは、オブジェクト作成(動的な性質)の間にどのようなタイプのCarも渡すことができます。したがって、その柔軟性のレベルは、has-a(組成)関係によって提供される。

これがあなたの疑いを解消することを願っています。