调用基方法而不是重写

本文关键字:重写 方法 调用 | 更新日期: 2023-09-27 18:13:37

在c#中,类A包含一个公共方法Foo(),它做一些处理并返回一个值。protected方法Bar(),也属于A类,执行与Foo()相同的逻辑,然后进行一些额外的处理,然后返回一个值。

为了避免重复代码,Bar()调用Foo()并使用返回值作为中间值。

class A
{
  public virtual String Foo()
  {
     String computedValue;
     // Compute the value.
     return computedValue;
  }
  protected String Bar()
  {
     String computedValue;
     String intermediateValue = Foo();
     /// More processing to create computedValue from intermediateValue.
     return computedValue;
  }
}

B继承自A并覆盖Foo()。重写调用Bar()的基类实现。

class B : A
{
   public override String Foo()
   {
     base.Bar();
   }
}

这(当然)进入一个无限循环,直到计算机内存耗尽,然后产生堆栈溢出异常。

最明显的解决方案是用私有FooInternals方法重写A,该方法包含Foo的核心。然后修改Foo和Bar以使用该方法的结果。

是否有办法强制a的Bar()调用a的Foo()而不是覆盖?

(我几乎肯定在这里太聪明了;这完全违背了多态性。但我还是忍不住想把我的知识再推进一点。

调用基方法而不是重写

是否有一种方法可以强制a的Bar()调用a的Foo()而不是重写?

不直接。最简单的重构是将Foo更改为:

public virtual string Foo()
{
    return FooImpl();
}
private string FooImpl()
{
    String computedValue;
    // Compute the value.
    return computedValue;
}

然后将Bar改为FooImpl,而不是Foo

(这可能是你在"最明显的解决方案"一段中的意思——恐怕我在第一次阅读时错过了。)

从根本上说,这只是继承存在问题的领域之一。当一个虚方法调用另一个虚方法时,需要对其进行文档记录,以便子类可以避免引起问题—即使感觉它应该是一个实现细节。正是这种事情使我更喜欢组合而不是继承——当然,两者都是合理的选择。