调用基本方法而不是覆盖

Tha*_*Guy 5 c# polymorphism

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

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

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

B继承A和覆盖Foo().覆盖调用的基类实现Bar().

class B : A
{
   public override String Foo()
   {
     base.Bar();
   }
}
Run Code Online (Sandbox Code Playgroud)

这(当然)进入无限循环,直到计算机内存不足然后产生堆栈溢出异常.

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

有没有办法强制A Bar()调用A Foo()而不是覆盖?

(我几乎肯定在这里过于聪明;这完全违背了多态性.但我无法抗拒尝试进一步推动我的知识的冲动.)

Jon*_*eet 7

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

不是直接的.最简单的重构是Foo改为:

public virtual string Foo()
{
    return FooImpl();
}

private string FooImpl()
{
    String computedValue;
    // Compute the value.
    return computedValue;
}
Run Code Online (Sandbox Code Playgroud)

然后Bar改为呼叫FooImpl而不是Foo.

(这可能就是你在"最明显的解决方案"段落中的意思 - 我在一读时错过了,我很害怕.)

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