Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execution flow of Method overriding and method hiding

I'm confused with the following scenario, we have a set of classes like this

public class A
{
    public virtual string SomeMethod()
    {
        return "A";
    }
}

public class B : A
{
    public override string SomeMethod()
    {
        return "B";
    }
}

public class C : B
{
    public new virtual string SomeMethod()
    {
        return "C";
    }
}

public class D : C
{
    public override string SomeMethod()
    {
        return "D";
    }
}

When i call the following method

private void Test()
{
    A a = new D();
    B b = new D();
    C c = new D();
    D d = new D();
    Console.WriteLine(a.SomeMethod()); //The method in class B is being called
    Console.WriteLine(b.SomeMethod()); //The method in class B is being called
    Console.WriteLine(c.SomeMethod()); //The method in class D is being called
    Console.WriteLine(d.SomeMethod()); //The method in class D is being called
}

I'm getting the output like this

B B D D

Why is it that the inherited method is being called, instead of the method in the declared type, and why isn't the method in class D being called every time?

like image 868
Vamsi Avatar asked Jan 15 '23 17:01

Vamsi


1 Answers

When you call SomeMethod on an instance of A (i.e. A foo = new <A or derived>()), you expect to get the most derived version of SomeMethod available. That's the whole point of inheritance. Your code only needs to deal with instances of the base class, but if those instances happen to really be of a derived class, the special dervied implementations are invoked. This is the behavior you get when you override a method.

This explains common scenarios like

A b = new B();
b.SomeMethod();  // B's implementation invoked

With new, you are not overriding the method, you are declaring a brand new method with the same name. This method exists only on the class that declared it and its children, it's not part of the base classes and their inheritance chain.

So what does A a = new D(); a.SomeMethod(); do? The variable is declared as A, so any methods/properties/etc invoked against it have to be defined on A. C defined a new method SomeMethod (and D overrides it), but this method doesn't exist on A, so it cannot be invoked here. The most derived implementation of SomeMethod (as declared on type A) is in B, so this is the implementation which is invoked.

Same story for B b = new D(); b.SomeMethod();

It's only when we get to C c = new D(); c.SomeMethod() that the new method has a chance to execute. This is because the variable is a C, and thus the new method SomeMethod is for the first time declared on the variable type. And as stated above, the most derived possible version will be invoked, which in this case means the version overriden by D.

And I hope we are all on the same page for D d = new D(); d.SomeMethod() :)

Others have posted good links. Here's another thread that might help: C# and method hiding

And the last example here shows an even weirder scenario where the "new" method is declared as private, thus a further dervied type actually inherits the base version of the method, rather than inheriting the "new" version. http://msdn.microsoft.com/en-us/library/aa691135

like image 125
latkin Avatar answered Jan 23 '23 04:01

latkin