【问题标题】:Why should an abstract class implement an abstract method of an abstract base class?为什么抽象类要实现抽象基类的抽象方法?
【发布时间】:2010-07-17 13:37:28
【问题描述】:

在以下示例中,类 Derived 实现了类 Main 的抽象方法 method。但是我想不出在抽象Derived类的实现中填写方法体的理由。当然,我应该只在真实类中实现抽象方法。

那么我怎样才能避免这样做呢?我还可以做些什么?

abstract class Main
{
    public abstract void method();
}
abstract class Derived : Main
{
    public override void method()
    { 
    }
}

class RealClass : Derived
{

}

【问题讨论】:

  • 我不明白你想要什么答案?你能详细解释一下你的问题吗?
  • "但是我找不到在派生抽象类中填充方法体内部的理由。"这句话是我的问题。

标签: c# .net design-patterns abstract-class


【解决方案1】:

通常,如果有人指定一个抽象类有一个抽象方法,要么是因为该类的某些功能依赖于该方法,要么是因为它是预期 API 的一部分,对它没有意义此时要实现的父类。在任何一种情况下,一旦您获得类的非抽象实现,必须有一个实现。

还要注意,如果您正在实现一个接口,您需要说明该接口将如何实现,即使您只是调用成员抽象并将责任传递给子类

public interface IPet {string GetNoise(); int CountLegs(); void Walk();}
public abstract class Pet : IPet
{
    public string Name {get; set;}
    public abstract string GetNoise(); // These must be here
    public abstract int CountLegs();
    public abstract void Walk();
}

在实现子类时,您有几个选择,具体取决于具体情况。如果您的实现本身是一个抽象类,则不需要实现抽象方法。

public abstract class Quadruped : Pet
{
    public override int CountLegs () { return 4; }
}

如果您的实现是非抽象的,但所讨论方法的标准原因确实不适用于您的情况,您可以执行无操作方法(在 void 方法的情况下),或返回一些虚拟方法值,甚至抛出 NotImplementedException 来指示该方法一开始就不应该被调用。

public class Fish : Pet
{
    public override string GetNoise() {return "";} // dummy value: fish don't make noise
    public override int CountLegs() {return 0;}
    public override void Walk() {} // No-op
    // public override void Walk() { throw new NotImplementedException("Fish can't walk"); }
}

这能回答你的问题吗?

【讨论】:

  • +1,很好的答案。严格来说,我认为Quadruped 中的CountLegs 方法应该是密封的,否则任何人都可以创建一个有3条腿的四足动物;)
  • 不错的答案。是的,这是问题的答案。使用界面帮助解决这个问题。
  • 另一种解决方案是,只需将 Main 方法定义为虚拟方法,然后在其中填充一个真实类,这样我就不需要在子抽象类上实现它。
  • @Thomas:为什么?见过三足狗吗?失去一条腿的狗可能不是四足类合同的“标准”履行,但三足狗仍然是四足狗,需要与完整的四足狗不同的门/步行。对于这种情况,我会想到动画和 CGI​​……
  • @Thomas & @Marjan: 实现应该是虚拟的还是默认密封的似乎是程序员之间真正的争论点,我对此没有强烈的看法,所以我不会以一种或另一种方式争论。谢谢你的笑声。 :-)
【解决方案2】:

如果Derived 中没有method 的实现,那么您也可以将Derived 抽象化:

abstract class Derived : Main
{
}

class RealClass : Derived
{
    public override void method() { ... }
}

编辑:澄清 cmets - 如果子类中没有抽象方法的有意义实现,则不需要提供。然而,这将要求派生类本身是抽象的,并且必须在某个具体子类的后代类链中的某处提供实现。我并不是说您应该将method 的实现留空,因为它在问题中,而是您删除Derived 中的覆盖并标记类抽象。这会强制 RealClass 提供一个实现(或本身被标记为抽象)。

【讨论】:

  • 我更新了问题。在我的示例中,已经派生是抽象的,但我忘记写了。但是VS2010还是实现了方法类。
  • @Freshblood - 你不能在Derived 中提供method 的任何实现。只有具体的类必须提供所有抽象成员的实现(直接或间接通过它们的父类)。
  • 所以最好的办法是在派生类中留下空的方法体?如果方法返回一个值,我们必须为它返回 null 或值,所以这不是好的设计。我正在寻找更好的。
  • @Freshblood - 任何抽象方法都必须在某个具体类的某个地方实现(在类本身或某个祖先中)。我并不是说您应该在 Derived 中将 method 留空,而是您应该完全删除对它的任何引用,这将需要一些子类来实现它。
  • 关键是省略你不想实现的虚方法。 IntelliSense 在这里有点笨拙。
【解决方案3】:

所有非抽象后代类必须提供抽象方法的具体实现。如果您不提供实现,则无法调用该方法。

如果某些具体类没有明显正确地实现抽象方法,那么您的对象设计是不正确的。也许你应该有一个带有一些抽象方法(但不是全部)的抽象类。该类可以有一个抽象的后代和一些具体的后代。

【讨论】:

    猜你喜欢
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 2016-11-08
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多