New vs Override

M

methodios

Hi
Can someone help me straighten out my train of thought... I want to
know what actually goes on behind the scene..step by step.

Here is the code:

-----------------
using System;

namespace Test
{
public class MyBase
{
public virtual string Meth1()
{
return "MyBase-Meth1";
}
public virtual string Meth2()
{
return "MyBase-Meth2";
}
}


class MyDerived : MyBase
{
public override string Meth1()
{
return "MyDerived-Meth1";
}
public new string Meth2()
{
return "MyDerived-Meth2";
}


public static void Main()
{
MyDerived mD = new MyDerived();
MyBase mB = (MyBase) mD;



System.Console.WriteLine(mD.Meth1()); // Displays: MyDerived-Meth1
System.Console.WriteLine(mB.Meth1()); // Displays: MyDerived-Meth1
System.Console.WriteLine(mB.Meth2()); // Displays: MyBase-Meth2
System.Console.WriteLine(mD.Meth2()); // Displays: MyDerived-Meth2
}


}

}

-------
Here is what I think is currently happening (please correct me if I'm
wrong).
Question 1) When mD.Meth1() is called, it checks the memory locaton in
the heap contained in mD and goes to that location. Now, it finds the
MyDerived object.

**HERE IS WHERE MY CONFUSION BEGINS**
What does it actually do? Does it do the following:
PATH 1 - Go into MyDerived and realize it's inheriting MyBase. It then
goes to MyBase and finds Meth1() and notice it to be a virtual
function. It comes back out of MyBase and goes back to MyDerived and
notice that the function has been correclty overriden and uses that
function.

OR

PATH 2 - Go into MyDerived and does not even bother going into MyBase.
It notices that it has that function in it and it's overridding the
base function and calls it.



Quesiton 2) When mB.Meth2() is called, since the object really being
used is still MyDerived, how come MyDerived.Meth2() isn't called? The
new function obviously hides it, and the object being worked on is
MyDervived...not MyBase.

Why does it take PATH 1 and go into MyBase and calls that function when
the function has a keyword NEW which hides it?

Please help!!!
 
J

Jesse McGrew

methodios said:
Here is what I think is currently happening (please correct me if I'm
wrong).
Question 1) When mD.Meth1() is called, it checks the memory locaton in
the heap contained in mD and goes to that location. Now, it finds the
MyDerived object.

**HERE IS WHERE MY CONFUSION BEGINS**
What does it actually do? Does it do the following:
PATH 1 - Go into MyDerived and realize it's inheriting MyBase. It then
goes to MyBase and finds Meth1() and notice it to be a virtual
function. It comes back out of MyBase and goes back to MyDerived and
notice that the function has been correclty overriden and uses that
function.

OR

PATH 2 - Go into MyDerived and does not even bother going into MyBase.
It notices that it has that function in it and it's overridding the
base function and calls it.

The latter.

Every class has a table with slots for each virtual method in the
class, where each slot points to the implementation of that method.
When you override a method in a derived class, the new implementation
simply replaces the old one in the derived class's virtual method
table. Calling a virtual method means looking up the virtual method
table, finding the slot corresponding to the method you want, and
jumping to the address found there. The type of the object doesn't
really even matter, only the addresses stored in the table.

We can imagine the table for MyBase looking like this (ignoring the
virtual methods inherited from System.Object, like ToString):

"Meth1" -> MyBase.Meth1
"Meth2" -> MyBase.Meth2

And for MyDerived:

"Meth1" -> MyDerived.Meth1
"Meth2" -> MyBase.Meth2

Since you used the "new" keyword, the compiler knows that
MyDerived.Meth2 isn't the same method as MyBase.Meth2, so mD.Meth2()
results in a call to the new method, not the old one. However, it can
only use that information when you call through a variable of the
derived type. When you call through a MyBase variable, the compiler can
only see the Meth2 defined in MyBase.
Quesiton 2) When mB.Meth2() is called, since the object really being
used is still MyDerived, how come MyDerived.Meth2() isn't called? The
new function obviously hides it, and the object being worked on is
MyDervived...not MyBase.

This is precisely the difference between overriding and hiding.
MyDerived.Meth2 isn't actually related to MyBase.Meth2; they just
happen to have the same name. At compile time, the method call is bound
to the derived version, not the base version, because of the type of
the variable you're using to call the method.

Jesse
 
M

Michael S

Jesse McGrew said:
The latter.

Every class has a table with slots for each virtual method in the
class, where each slot points to the implementation of that method.
When you override a method in a derived class, the new implementation
simply replaces the old one in the derived class's virtual method
table. Calling a virtual method means looking up the virtual method
table, finding the slot corresponding to the method you want, and
jumping to the address found there. The type of the object doesn't
really even matter, only the addresses stored in the table.

We can imagine the table for MyBase looking like this (ignoring the
virtual methods inherited from System.Object, like ToString):

"Meth1" -> MyBase.Meth1
"Meth2" -> MyBase.Meth2

And for MyDerived:

"Meth1" -> MyDerived.Meth1
"Meth2" -> MyBase.Meth2

Since you used the "new" keyword, the compiler knows that
MyDerived.Meth2 isn't the same method as MyBase.Meth2, so mD.Meth2()
results in a call to the new method, not the old one. However, it can
only use that information when you call through a variable of the
derived type. When you call through a MyBase variable, the compiler can
only see the Meth2 defined in MyBase.


This is precisely the difference between overriding and hiding.
MyDerived.Meth2 isn't actually related to MyBase.Meth2; they just
happen to have the same name. At compile time, the method call is bound
to the derived version, not the base version, because of the type of
the variable you're using to call the method.

Jesse

Well written Jesse.

Also just to add:

A reintroduced call is fast as the compiler can go the type od the reference
and simply call the method.

A overridden call is slower as the runtime must access your object, access
its type (VTable) and call the correct method.

- Michael S

ps.
I still think that Delphis keyword 'reintroduce' is better than 'new'
 
B

Brian Gideon

In addition to what others have said notice that you get the same
behavior without the 'new' modifier. You do get a warning from the
compiler telling you that a derived class is hiding an inherited
member. The 'new' modifier is a way to explicitly tell the compiler
that hiding is indeed what you intended. But, it doesn't actually
change the execution of code in any way. That's a good thing. Let me
give you a practical example to show you why.

Consider the following code.

// This is provided by the Wizbang Widget Company
public class Widget
{
public virtual void Foo() { }
public virtual void Bar() { }
}

// You decide to extend the Widget class to make it better.
public class BetterWidget : Widget
{
public void Initialize()
{
// Code to initialize the class goes.
}
}

Later, the Wizbang Widget Company decides that they need to add a
mechanism for initializing the Widget so naturally they add an
Initialize method.

public class Widget
{
public virtual void Foo() { }
public virtual void Bar() { }
public void Initialize() { }
}

Can you believe that. They added a method to their Widget class with
the same name as an existing method in your derived class! What are
the odds of that?!

In this case all existing BetterWidget references will still use the
BetterWidget.Initialize implementation and any new uses of the
Initalize method on a Widget reference will use the Widget.Initialize
method. You will get a compiler warning, but everything works as
expected without any modifications to the code.

Can you see why it would have been worse had the C# compiler generated
an error or changed the way the methods were called?

Brian
 

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