【问题标题】:Achieve Inheritance/reusing functionality/properties from multiple parents从多个父级实现继承/重用功能/属性
【发布时间】:2017-02-15 06:13:35
【问题描述】:

注意:在将其标记为重复或关闭之前,请考虑阅读完整问题,您可能更愿意建议编辑而不是关闭它。

更新 是的,我知道 c# 不允许多重继承,但当然它实际上需要一些时间,如以下场景,所以请指导,为什么不需要它或如何实现它


我需要在一个孩子中继承/重用来自不同类的功能/成员。我有课

abstract class Hurdle
{       
   public virtual void setPositionInCells(){somecode_sp();}
   public virtual void OnHit(){somecode_h();}
}

我真正需要的课程是MovableSingleCellHurdleMovableMultiCellHurdleStationarySingleCellHurdleStationaryMultiCellHurdle

但在 C# 中我只能这样做

class SingleCellHurdle: Hurdle
{
 public int CellNumber;
 public override void setPositionInCells(){ base(); somecode_sp1();}
}
class MultipleCellHurdle: Hurdle 
{
 public int[] CellNumbers;
 public override void setPositionInCells(){ base(); somecode_sp2();}
}

class MovableHurdle: Hurdle
{
 public float HitForce;
 public override void OnHit() { base(); somecode_h1();}
}
class StationarHurdle: Hurdle
{
 public override void OnHit() { base(); somecode_h2();}
}

但我坚持做以下事情

class MovableSingleCellHurdle: MovableHurdle, SingleCellHurdle
{
   public override void OnHit() { base();}
   public override void setPositionInCells() { base();}
   public int getLastHitForce()
   {
       return HitForce;
   }
   public int getLastPositionCells()
   {
       return CellNumber;
   }
}

我需要做的是,我不应该再为真实课程重复setPosition()OnHit()的代码

我目前正在做的根本不是继承/重用,因为它不允许我制作上述所需的结构

我应该在几年前就知道了,可惜找不到专门针对这种继承场景的文章/博客。

如果您认为这个问题值得投反对票,那没关系,但也请指导我。如果我做错了,那么请指导我应该使用什么方法?或者哪篇文章完全解释了使用最佳 oop 实践处理这种情况

【问题讨论】:

  • 首先,C# 不允许从多个类继承。那么您的MovableSingleCellHurdle 无效。此外,base() 无效。你可能指的是base.baseMethod()
  • 您是否将组合视为继承的替代方案?
  • @FacticiusVir,我一定是因为在组合/继承的良好概念方面很差,所以你能指导一下我在哪里看起来像这样或者我应该如何看待它
  • 我认为这里的主要问题是您的帖子不是一个问题。 这里的问题是什么?
  • @Sami 这是一个合理的介绍:codingdelight.com/tag/composition-over-inheritance

标签: c# oop inheritance multiple-inheritance reusability


【解决方案1】:

C# 不支持多重继承。一种方法是这样的:

class Hurdle { ... }
class SingleCellHurdle : Hurdle { ... }
class MultipleCellHurdle : Hurdle { ... }
class MovableSingleCellHurdle : SingleCellHurdle { ... }
class MovableMultipleCellHurdle : MultipleCellHurdle { ... }    
class StationarySingleCellHurdle : SingleCellHurdle { ... }
class StationaryMultipleCellHurdle : MultipleCellHurdle { ... }

显然,这仅在具有此类关系的类相对较少时才实用。您拥有的此类关系越多,它就会成倍增长。

【讨论】:

  • 或者我可以继承 MovableSingleCellHurdle : MovableHurdleMovableMultipleCellHurdle : MovableHurdle。是的,这是一种选择,但感觉非常无助
【解决方案2】:

在这种情况下,您不能也不应该使用继承。

之所以基于LSP(Liskov Substitution Principle)。

为了更清楚地了解 LSP:您可能break LSP as explained here。但这只是学术。您可以忽略或根据您的里程研究它。

解决方案很可能是委托。

首先,您需要在更简单的类和更丰富的类之间建立 have-a 关系,如下所示:

class MovableSingleCellHurdle
{
    private MovableHurdle mh;
    private SingleCellHurdle sch;

接下来,您委派对这些类的任何调用,如下所示:

    public void OnHit()
    {
        mh.OnHit();
        // or: sch.OnHit();
    }

如果一个方法有参数,传递它们,如果它们返回一些东西,返回它,像这样:

    public int SumAndFloor(double a, double b)
    {
        return internalDelegateClass.SumAndFloor(a, b);
    }

这种模式称为组合,因为您通过利用更简单的对象来组合对象。

您调用内部方法的事实是delegation

此外,您想使用构造函数构造对象。这叫constructor injection

    public MovableSingleCellHurdle(MovableHurdle mh, SingleCellHurdle sch)
    {
        this.mh = mh;
        this.sch = sch;
    }

【讨论】:

  • 我认为在这种情况下继承不会破坏 liskov。鉴于所提供的信息,我看不出有什么理由不能在需要派生较少的实例的情况下使用派生较多的类实例。
  • 是的,听起来不错,我会阅读更多关于这种类型的代表作文并实际解决它,我希望这是必需的答案。
  • @rory.ap 我同意,没有迹象表明违反了 LSP。但是这种推理是倒退的(我们说“我们所看到的并不违反 LSP”)。关键是你必须证明 LSP 在所有情况下都没有被违反,但我们不知道所有这些情况是什么。这就是为什么我说可能并更好地保存它。更准确地说:我们不知道somecode_h1() 做了什么。违反 LSP 是可能的,但无法证明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 2012-08-15
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多