【问题标题】:How to mulitiply inherit from abstract base classes?如何从抽象基类乘以继承?
【发布时间】:2021-02-23 07:27:46
【问题描述】:

我有一些抽象基类可用于多个实现。

基类:

public abstract class BaseX
{
    public string A { get; set; }
}

public abstract class BaseY : BaseX
{
    public string B { get; set; }
}

对于每个用例,我想从这些基类创建特定的类,例如:

public abstract SpecificX : BaseX
{
    public string C { get; set; }
}

public abstract SpecificY : BaseY
{
    public string D { get; set; }
}

SpecificY 派生的所有类都应包含所有属性 A、B、C、D。

我现在的问题是,SpecificY 没有来自SpecificX 的属性 C,因为我不能像这样进行多重继承

public abstract SpecificY : BaseY, SpecificX

我唯一的想法是使用这样的接口:

public Interface ISpecificX
{
    string C { get; set; }
}

public abstract SpecificX : BaseX, ISpecificX
{
    public string C { get; set; }
}

public abstract SpecificY : BaseY, ISpecificY
{
    public string D { get; set; }
    public string C { get; set; } <== redundancy
}

但是我需要实现 C 两次。一旦 C 变得不仅仅是一个简单的属性,事情就会变得丑陋。有没有更好的方法来创建这种结构?

提前致谢,
弗兰克

【问题讨论】:

  • 代替继承,你可以考虑使用你认为你的基类应该是的实例。这样一来,您就可以拥有一个、两个甚至没有所有这些属性。
  • 这能回答你的问题吗? Multiple Inheritance in C# 并在 composition 上查找 Chris's answer
  • 请更正您的问题,因为我看不到像 SpecificBSpecificA 这样的课程
  • 抱歉,SpecialB|A 输入错误...在问题中更正了
  • @MickyD 感谢您的链接。它并没有真正回答这个问题,或者说,我对组合解决方案非常不满意,可能宁愿做一个接口解决方法来减少SpecificY中冗余的开销以及超出的范围

标签: c# inheritance multiple-inheritance


【解决方案1】:

我强烈建议 favour composition over inhertiance - 正如 GoF 所支持的那样。这样您就不会继承给定的类,而只是使用它的一个实例。然后,您可以轻松拥有所有属性而无需任何重复:

class BaseX { ... }
class BaseY { ... }

class SpecificY : BaseY
{
    private readonly SpecificX b = new SpecificX();
    public string A { get => this.b.A; set => this.b.A = value; } // delegate the call
    public string B { get; set; }
    public string C { get => this.b.C; set => this.b.C = value; } // delegate the call
    public string D { get; set; }
}

【讨论】:

  • 组合优于继承的问题在于,您不能将组合(成员)对象当作对其所有者的引用一样传递——也不能覆盖方法。继承组合在基于消息传递的语言(如 Smalltalk 和 Objective-C)或对 mixin 和特征具有一流支持的语言(因此允许多态性)中效果最佳。 C# 既没有消息传递也没有特征——这使得多态类组合成为一种非常痛苦和令人沮丧的体验。
  • 是的,例如如果我想传递SpecificX 类型的变量,我不能传递SpecificY 的对象。另外,我经常使用这种结构: if (myObject is SpecificX specificXInstance) { ... } 这不适用于组合。这可以通过接口解决,但我又回到了起点,因为我需要确保来自 SpecificX 的所有新属性/方法也在 SpecificY 中。
  • 另外,我对属性使用属性,这可能不会出现在委托属性上。
  • @Aaginor "如果我想传递一个SpecificX类型的变量,我不能传递一个SpecificY的对象" - 这是你的代码的限制并且存在是否使用合成。你的两个图中唯一的共同点是 SpecificXSpecificY 最终派生自 BaseX 所以在这种情况下没有什么能阻止你传递 SpecificY 的实例。同样执行像if (myObject is SpecificX specificXInstance) 这样的显式检查也违背了OOP 的目的。我认为你需要重新考虑你的树
  • @Aaginor 我的意思是你的继承树似乎没有意义。例如如果你要用AnimalDogCatHusky 替换BaseXBaseYSpecificXSpecificY,你很快就会明白为什么public abstract SpecificY : BaseY, SpecificX 不起作用。地球上没有任何生物以猫为父母,以狗为父母……哈士奇! ;) 您的示例 “我想传递一个SpecificX 类型的变量,我不能传递一个SpecificY 的对象” can 如果该方法可以正常工作,则为真在Animal。希望这会有所帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-01
  • 2013-12-24
  • 1970-01-01
  • 2012-05-20
  • 1970-01-01
相关资源
最近更新 更多