在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();
}
}
这(当然)进入无限循环,直到计算机内存不足然后产生堆栈溢出异常。
最明显的解决方案是使用包含Foo内容的私有FooInternals
方法重写A.然后修改Foo和Bar以使用该方法的结果。
有没有办法强迫A Bar()
拨打A Foo()
而不是覆盖?
(我几乎肯定在这里过于聪明;这完全违背了多态性。但我无法抗拒尝试进一步推动我的知识的冲动。)
答案 0 :(得分:7)
有没有办法强制A的Bar()调用A的Foo()而不是覆盖?
不直接。最简单的重构是将Foo
更改为:
public virtual string Foo()
{
return FooImpl();
}
private string FooImpl()
{
String computedValue;
// Compute the value.
return computedValue;
}
然后更改Bar
以致电FooImpl
而不是Foo
。
(这可能就是你在“最明显的解决方案”段落中的意思 - 我在一读时错过了,我很害怕。)
从根本上说,这只是继承存在问题的领域之一。当一个虚拟方法调用另一个虚拟方法时,需要对其进行记录,以便子类可以避免导致问题 - 即使感觉它应该是一个实现细节。正是这种事情让我更喜欢构图而不是继承 - 当然,两者都是合理的选择。