CHAPTER 6 UNDERSTANDING INHERITANCE AND POLYMORPHISM
Understanding Member Shadowing
C# provides a facility that is the logical opposite of method overriding, termed shadowing. Formally
speaking, if a derived class defines a member that is identical to a member defined in a base class, the
derived class has shadowed the parent’s version. In the real world, the possibility of this occurring is the
greatest when you are subclassing from a class you (or your team) did not create yourselves (for
example, if you purchase a third-party .NET software package).
For the sake of illustration, assume you receive a class named ThreeDCircle from a coworker (or
classmate) that defines a subroutine named Draw() taking no arguments:
class ThreeDCircle
{
public void Draw()
{
Console.WriteLine("Drawing a 3D Circle");
}
}
You figure that a ThreeDCircle “is-a” Circle, so you derive from your existing Circle type:
class ThreeDCircle : Circle
{
public void Draw()
{
Console.WriteLine("Drawing a 3D Circle");
}
}
After you recompile, you find the following warning:
'Shapes.ThreeDCircle.Draw()' hides inherited member 'Shapes.Circle.Draw()'. To make the
current member override that implementation, add the override keyword. Otherwise add the new
keyword.
The problem is that you have a derived class (ThreeDCircle) that contains a method that is identical
to an inherited method. To address this issue, you have two options. You could simply update the
parent’s version of Draw() using the override keyword (as suggested by the compiler). With this
approach, the ThreeDCircle type is able to extend the parent’s default behavior as required. However, if
you don’t have access to the code defining the base class (again, as would be the case in many thirdparty libraries), you would be unable to modify the Draw() method as a virtual member, as you don’t
have access to the code file!
As an alternative, you can include the new keyword to the offending Draw() member of the derived
type (ThreeDCircle, in this example). Doing so explicitly states that the derived type’s implementation is
intentionally designed to effectively ignore the parent’s version (again, in the real world, this can be
helpful if external .NET software somehow conflicts with your current software).
// This class extends Circle and hides the inherited Draw() method.
class ThreeDCircle : Circle
{
// Hide any Draw() implementation above me.
public new void Draw()
239