C# Pattern for shadowing member variables?

M

Mark Sisson

Hi all.

SITUATION
================
1. I have a base class with a member variable that's an object
2. I have several classes that inherit from the base class.
3. There are several methods in the base class that modify the member
variable 4. I would like to have the inherited classes override the
member variable with a new var that's a subclass of the parent's
member variable
5. When someone instantiates the subclass and calls a methods that is
only implemented by the parent class, I like that parent method to
reference the overridden member variable.

EXAMPLE
===================================
class AAA
{
public YYY m_var = new YYY();

public void TestMethod() {

//HERE I WAS HOPING THAT localvar WOULD REFERENCE A ZZZ
CLASS
//INSTANCE HERE I WAS HOPING THAT BY USING THE this KEYWORD
THAT
//THE RUNTIME CLR WOULD RECOGNIZE THAT this IS OF TYPE ZZZ
SO THE
//m_var RETURNED WOULD BE OF TYPE ZZZ.

YYY localvar = this.m_var;

//BUT IT DOESN'T....

Type t = localvar.GetType();
Debug.Print(t.FullName);
}
}

class BBB : AAA
{
public ZZZ m_var = new ZZZ();
}

class YYY
{
}

class ZZZ : YYY
{
}


Any recommendations or new patterns that might help out?
TIA
 
P

Patrik Löwendahl [C# MVP]

There's two approaches to solving your problem.

1) Mark the field with protected in the base class, create a constructor on
the sub class that initilizes the field.

class Mammal
{
protected string Name = "Mammal";

public void MakeNoise()
{
Console.WriteLine("The mammal {0} made some noise", this.Name);
}
}

class Mammoth : Mammal
{
public Mammoth()
{
this.Name = "Mammoth";
}
}

2) Create virtual properties and access the variable through them,
properties behave as methods and could be marked as virtual and then be
overriden in the sub class.
 
Q

q

From MSDN

Name hiding through inheritance occurs when classes or structs redeclare
names that were inherited from base classes. This type of name hiding
takes one of the following forms:

A constant, field, property, event, or type introduced in a class or
struct hides all base class members with the same name.
A method introduced in a class or struct hides all non-method base class
members with the same name, and all base class methods with the same
signature (method name and parameter count, modifiers, and types).
An indexer introduced in a class or struct hides all base class indexers
with the same signature (parameter count and types).
The rules governing operator declarations (Section 10.9) make it
impossible for a derived class to declare an operator with the same
signature as an operator in a base class. Thus, operators never hide one
another.

Contrary to hiding a name from an outer scope, hiding an accessible name
from an inherited scope causes a warning to be reported. In the example

class Base
{
public void F() {}
}
class Derived: Base
{
public void F() {} // Warning, hiding an inherited name
}
the declaration of F in Derived causes a warning to be reported. Hiding
an inherited name is specifically not an error, since that would
preclude separate evolution of base classes. For example, the above
situation might have come about because a later version of Base
introduced an F method that wasn't present in an earlier version of the
class. Had the above situation been an error, then any change made to a
base class in a separately versioned class library could potentially
cause derived classes to become invalid.

The warning caused by hiding an inherited name can be eliminated through
use of the new modifier:

class Base
{
public void F() {}
}
class Derived: Base
{
new public void F() {}
}
The new modifier indicates that the F in Derived is "new", and that it
is indeed intended to hide the inherited member.

A declaration of a new member hides an inherited member only within the
scope of the new member.

class Base
{
public static void F() {}
}
class Derived: Base
{
new private static void F() {} // Hides Base.F in Derived only
}
class MoreDerived: Derived
{
static void G() { F(); } // Invokes Base.F
}
In the example above, the declaration of F in Derived hides the F that
was inherited from Base, but since the new F in Derived has private
access, its scope does not extend to MoreDerived. Thus, the call F() in
MoreDerived.G is valid and will invoke Base.F.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top