2012-05-03 19 views
-1

私は多重継承を研究していますが、それは悪い設計とみなされています。複数の継承を削除する

私は、多重継承が便利な例を作成しましたが、複数の継承を削除するためにそれを書き直す方法が見つかりませんでした。
さらに、多くの言語は多重継承をサポートしておらず、新しい設計が必要です。

「動物」クラスは、すべての動物が行う多くのことを実装しています。
'AquaticAnimal'クラスは水に関するすべてを実装します。
'TerrestrialAnimal'クラスは、土地の動物に関するすべてを実装します。

'Amphibious'クラスは、 'AquaticAnimal'と 'TerrestrialAnimal'でできることすべてを行うことができる動物用に作成されました。
このアプリケーションでは、動物園、水瓶座、平野、水陸両生類の陸上で「水陸両用」動物を使用する必要があります。

Amphibious.eat()を呼び出すとAnimal.eat()が2回呼び出され、矛盾した状態になるため、仮想継承にもかかわらず、ダイヤモンドの問題は継続します。

実際のプログラミング言語ではありませんが、Java/C++と似ています。

class Animal{ 
    private: 
    Place birthplace; 
    String name; 
    List likesToEat; 
    Stomach stomach; 

    public: 
    virtual void growl(){ ... } 

    virtual int eat(Food food){ 
     ... test if likes 
     ... many operations 
     chew() 
     ... 
     stomach.fill(food); 
    } 
} 

class FlyingAnimal extends Animal { 
    private: 
    Wings wings; 
    public: 
    void fly(){ ... wings.move(); ... } 
} 
class AquaticAnimal extends Animal{ 
    private: 
    Flipper flipper; 

    public: 
    void swim(){ ... flipper.move(); ... } 

    int eat(Food food){ 
     int x = Animal.eat(food); 
     ... use x 
     flipper.nourish(food); 
    } 
} 
class TerrestrialAnimal extends Animal{ 
    private: 
    Legs legs; 

    public: 
    void run(){ ... legs.move(); ... } 

    int eat(Food food){ 
     int x = Animal.eat(food); 
     ... use x 
     legs.nourish(food); 
    } 
} 
class Amphibious extends AquaticAnimal, TerrestrialAnimal{ 
    public: 
    int eat(Food food){ 
     AquaticAnimal.eat(food); 
     TerrestrialAnimal.eat(food); 
     //PROBLEM: Animal.eat() will be called twice. 
    } 
} 

//------------------------------------------ 
class Zoo { 
    public: 
    void add/remove(Animal a); 
    void feed(Animal a); 
    void show(Animal a); 
} 
class Aquarius { 
    public: 
    void add/remove(AquaticAnimal a); 
} 
class Plains { 
    public: 
    void add/remove(TerrestrialAnimal a); 
} 
class HighPeaks { 
    public: 
    void add/remove(FlyingAnimal a); 
} 
class AmphibiousRace { 
    public: 
    void add/remove(Amphibious a); 
    void enterIntoLake(Amphibious a); 
    void exitFromLake(Amphibious a); 
} 
+0

これには疑問符もありません。質問がありますか、これはちょうど脳のダンプですか? –

+0

質問:複数の継承を削除するためにこのコードを書き直すにはどうすればいいですか? – Squall

答えて

0

それは水陸両用動物が両方から継承すると言うことは本当に有効であり、水生および陸生動物を区別足と足ひれをうか?多くの動物には脚と羽毛があります。

いずれかの方法、あなたがクラスに必要とされている部分を通過し、組成アプローチの多くを使用できます。

ラフの例を少しですが、うまくいけば、それはあなたのアイデアを与える
class Animal{ 
    private: 
    Place birthplace; 
    String name; 
    List likesToEat; 
    Stomach stomach; 

    public: 

    virtual IEnumerable<Movement > Movements { get; } 
    virtual IEnumerable<IAppendage> Appendages{ get; } 

    virtual void growl(){ ... } 

    virtual int eat(Food food){ 
     ... test if likes 
     ... many operations 
     chew() 
     ... 
     stomach.fill(food); 
    } 
} 

interface IAppendage { 
    void Move(); 
} 

class Wings : IAppendage {} 
class Legs: IAppendage {} 
class Flippers : IAppendage {} 


class Movement { 
    private: 
    IAppendage AppendageForMovement { get; } 
    public : 
    void Go(){ 
    AppendageForMovement.Move(); 
    } 
} 

class FlyingMovement : Movement {} 
class RunningMovement : Movement {} 
class SwimmingMovement : Movement {} 

class AmphibiousAnimal extends Animal { 

private: 
    Flippers flipper; 
    Legs leg; 
    virtual IEnumerable<Movement > Movements { get { return new Movement [] { new SwimmingMovement(flipper), new RunningMovement(leg) } ; } 
    virtual IEnumerable<IAppendage> Appendages { get { return new IAppendage[] {new Wings() } } 

    public: 
    void fly(){ // find flying movement 
      ... 
      flyingMovement.Go(); 
      ... 
    } 
} 

。すべての機能を基本クラスに結びつけようとするのではなく、必要な機能を渡してみてください。複数のタイプの機能(実行中や歩行、水泳など)が必要な場合は、ヘルパークラスを渡してその機能を提供してください。

関連する問題