【问题标题】:Removing multiple inheritance移除多重继承
【发布时间】:2012-05-03 01:40:19
【问题描述】:

我正在研究多重继承,我读到它被认为是糟糕的设计。

我创建了一个多继承有用的示例,但我还没有找到重写它以删除多继承的方法。
此外,许多语言不支持多重继承,因此需要新的设计。

“Animal”类实现了所有动物都会做的许多事情。
“AquaticAnimal”类实现了关于水的一切。
'TerrestrialAnimal' 类实现了关于陆地动物的一切。

“Amphibious”类是为可以做“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);
}

【问题讨论】:

  • 这里面连问号都没有。你有什么问题,还是这只是一个脑残?
  • 问题是:如何重写这段代码来去除多重继承?
  • 我知道这是一个老问题,但今天解决这个问题的最好方法是使用 mixins 或特征。见:alisoftware.github.io/swift/protocol/2015/11/08/…

标签: oop inheritance multiple-inheritance code-reuse


【解决方案1】:

如果区分水生动物和陆生动物的是腿和脚蹼,那么说两栖动物继承自两者真的有效吗?没有多少动物既有腿又有脚蹼。

无论哪种方式,您都可以使用更多的组合方法,将所需的部分传递给类:

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(); 
           ... 
    }
}

这是一个粗略的例子,但希望它能给你带来想法。与其尝试将所有功能绑定到基类中,不如尝试传递您需要的功能。如果您需要不止一种类型的功能(例如跑步、步行和游泳),那么您只需传递更多帮助类来提供该功能。

【讨论】:

    猜你喜欢
    • 2010-09-27
    • 2012-03-07
    • 2012-09-18
    • 2012-06-02
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多