In C#, class A
contains a public method Foo()
which does some processing and returns a value. protected
method Bar()
, also in class A
performs the same logic as Foo()
, followed by some additional processing, and then returns a value.
In order to avoid duplicating code, Bar()
calls Foo()
and uses the return as an intermediate value.
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;
}
}
Class B
inherits from A
and overrides Foo()
. The override calls the base class implementation of Bar()
.
class B : A
{
public override String Foo()
{
base.Bar();
}
}
This (of course) goes into an infinite loop until the computer runs out of memory and then yields a stack overflow exception.
The most obvious solution is to rewrite A with a private FooInternals
method which contains the guts of Foo. Foo and Bar are then modified to use the results of that method.
Is there a way to force A's Bar()
to call A's Foo()
instead of the override?
(I'm almost certainly being way too clever here; this goes completely against polymorphism. But I can't resist the urge to try pushing my knowledge a bit further.)
Is there a way to force A's Bar() to call A's Foo() instead of the override?
Not directly. The simplest refactoring would be to change Foo
to:
public virtual string Foo()
{
return FooImpl();
}
private string FooImpl()
{
String computedValue;
// Compute the value.
return computedValue;
}
Then change Bar
to call FooImpl
instead of Foo
.
(This is probably what you meant in your "most obvious solution" paragraph - which I missed on the first reading, I'm afraid.)
Fundamentally this is just one of those areas where inheritance is problematic. When one virtual method calls another one, that needs to be documented so that subclasses can avoid causing problems - even though it feels like it should be an implementation detail. It's this sort of thing that makes me prefer composition over inheritance - where both are reasonable options, of course.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With