Fundamental OO Question

F

Frank

I'm relatively new to the OO game and for the most part feel I
understand it (at least at some level), however, something has me all
messed up.

Please consider the following:

public class Base
{
protected int _variable;

public Base(){}

public int SetVariable
{
set {_variable = value;}
}
}

// does nothing (in this example)
public class Derived : Base
{
public Derived() : base() {}
}

public class FurtherDerived : Derived
{
public FurtherDerived() : base() {}

public new int SetVariable
{
set {_variable = value * 2;}
}
}

public class Test
{
public Test()
{
bool someCondition = true;

Derived obj;

// Just to show why I may be doing this
if(someCondition)
obj = new Derived();
else
obj = new FurtherDerived();

// I want this to call the property accessor in FurtherDerived
// but instead it calls the accessor from Base.
obj.SetVariable = 5;
}
}

So, basically when I call the method in 'FurtherDerived' that
explicitly hides the base class' implementation I find that the base
class' method is still getting called.

I think I partially understand the mechanism by which this is happening
but I don't understand why its happening. Because I've created 'obj'
as a 'Derived' type, when the method call is made it goes to the
Derived class sees that there is no implementation for my method and
goes to the base class. However the part I don't understand is that
because I have defined my obj as 'FurtherDerived', when I instantiate
it the constuctor of 'FurtherDerived' gets called. If it knows to call
the constructor of FurtherDerived then why doesn't it go to the method
in FurtherDerived? Also, when I check the type of obj just before the
method call I can see that it is a FurtherDerived type.

So I'm not sure why the SetVariable method of the FurtherDerived class
doesn't get called.

Do I have to rewrite the above to look like this. And if so, why?:

public Test()
{
bool someCondition = true;

// Just to show why I may be doing this
if(someCondition)
Derived obj = new Derived();
else
FurtherDerived obj = new FurtherDerived();

// I want this to call the property accessor in FurtherDerived
// but instead it calls the accessor from Base.
obj.SetVariable = 5;
}


Thanks
Frank
 
M

Mattias Sjögren

So, basically when I call the method in 'FurtherDerived' that
explicitly hides the base class' implementation I find that the base
class' method is still getting called.

Right, that's the behavior you get when you use the "new" modifier to
hide a base class member. It breaks the polymorphism so you can't call
the new member through a reference to a base class.

If it knows to call
the constructor of FurtherDerived then why doesn't it go to the method
in FurtherDerived?

You will always call the constructor of the exact type you're
creating. Constructors aren't inherited and you specify the type to
create so that's no problem.

It doesn't call FurtherDerived.SetVariable because you're calling
through a Derived reference and because you used the "new" modifier
FurtherDerived.SetVariable is a different member than
Derived.SetVariable (or actually Base.SetVariable).

Do I have to rewrite the above to look like this. And if so, why?:

No, that wouldn't even compile. What you probably want to do is to use
virtual/override instead of "new".

public class Base
{
public virtual int SetVariable
{
set {_variable = value;}
}
}

public class FurtherDerived : Derived
{
public override int SetVariable
{
set {_variable = value * 2;}
}
}


I should also mention that according to the .NET naming guidelines
your property name shouldn't start with "Set", it should just be
"Variable".


Mattias
 
F

Frank

Mattias

Thanks for the quick response. As I was writing the message the
reasoning behind it became a little more clear but I just wanted to
confirm.

How does one decide when to use virtual/override or new? I mean in
this example its quite clear as there latter doesn't work but say I had
the SetVariable method in the Derived class - would I still use
virtual/override, or would I use new? In this case both would work
correct?

Thanks,
Frank

PS The SetVariable naming was simply for this example. Thanks for the
heads-up though.
 
T

Truong Hong Thi

Do I have to rewrite the above to look like this. And if so, why?:
No, that wouldn't even compile. What you probably want to do is to use
virtual/override instead of "new".
Just for more information, the OP can also cast:
if (someCondition)
obj.SetVariable = 5;
else
((FurtherDerived) obj).SetVariable = 5;
 

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