2012-05-03 107 views
-1

我正在研究多重繼承,並且我讀到它被認爲是糟糕的設計。刪除多重繼承

我創建了一個示例,其中多重繼承將是有用的,我還沒有找到一種方法來重寫它以刪除多重繼承。
此外,許多語言不支持多繼承,需要新的設計。

'動物'類實現了許多動物所做的事情。
'AquaticAnimal'類實現了有關水的一切。
'TerrestrialAnimal'類實現了陸上動物的一切。

'兩棲'類是爲動物創造的,它可以做任何'水生動物'和'陸生動物'都可以做的事情。
該應用程序需要在類:動物園,水瓶座,平原和兩棲類使用'兩棲'動物。

儘管虛擬繼承,鑽石問題仍然存在,因爲調用Amphibious.eat()將調用Animal.eat()兩次,並且會導致不一致的狀態。

它不是一種真正的編程語言,但它就像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(); 
      ... 
    } 
} 

這是一個有點粗糙的例子,但我希望它給你的想法。與其試圖將所有功能綁定到基類嘗試傳遞所需的功能。如果您需要多種類型的功能(例如跑步,步行和游泳),則只需傳入更多的輔助類即可提供該功能。