1

I was reading this post Overriding vs method hiding

And I read that "..When a virtual method is called on an object, then the most derived version of the method is called"

But when I execute the following code:

class A
{
    public virtual void print()
    {
        Console.WriteLine("A called");
        Console.Read();
    }
}

class B :A
{
    public override void print()
    {
        Console.WriteLine("B called");
        Console.Read();
    }
}

class C : B
{
    public override void print()
    {
        Console.WriteLine("C called");
        Console.Read();
    }
}

static void Main(string[] args)
{
    B b = new B();
    b.print(); it prints B?

}

It prints B . Shouldnt it be "C" if the above quoted statement is true? What am I missing? What is meant by "most derived" in this context?

SamuraiJack
  • 5,131
  • 15
  • 89
  • 195
  • The most derived of the actual instance is called - if you instantiate B, then B will be printed. Try `A a = new B(); a.print();` or `A a = new C(); a.print();` – Marwie Jan 07 '16 at 12:36
  • @Marwie It would print A – SamuraiJack Jan 07 '16 at 12:37
  • No it would print B or C. Try it. – Marwie Jan 07 '16 at 12:41
  • As a thought experiment, imagine another class `D : B`... if it was supposed to output "C called" in your example, with the extra class would it write "C called" or "D called" (obviously the answer is neither). – Anthony Jan 07 '16 at 13:07

3 Answers3

1

It would call method from the type on which instance it is called, you are calling it using instance of class B, so implementation of B will be invoked, if you were using instance of class C then overridden implementation of C class would get invoked.

For example:

class B :A
{
    public override void print()
    {
        Console.WriteLine("B called");
        Console.Read();
    }
    public virtual void printfromB()
    {
        Console.WriteLine("printfromB in B called");
        Console.Read();
    }
}
class C : B
{
    public override void print()
    {
        Console.WriteLine("C called");
        Console.Read();
    }
    public override void printfromB()
    {
        Console.WriteLine("printfromB in C called");
        Console.Read();
    }
}

now if you call it like:

static void Main(string[] args)
{
    A a = new C();
    a.print(); // it prints C (most derived implementation called) 
    B b = new C();
    b.printfromB(); // it prints "printfromB in C called"

}
Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
  • but then why use "most derived" version the author could have just said "derived" version. Is there something more to it? – SamuraiJack Jan 07 '16 at 12:36
  • author may have meant to say that if you create instance of most derived, then override implementation of most derived would be called. – Ehsan Sajjad Jan 07 '16 at 12:39
  • @Arbaaz You've overriden the same method twice. So if you execute `a.print()` as in Ehsan Sajjad's example, the most derived version of the method is executed. In case of an instance of C, the `print` method of C will win - even when C is derived from B which itself implements `print` already. – Marwie Jan 07 '16 at 12:48
0

There's no way that C will be ever be called when the actual type is B.

The original "Most derived" term can be understood using the following:

A data = new C();
data.print();

Even though the compiler treats data as A, the most derived (not A.print or B.print but C.print) version will be invoked (and that's because the method is virtual).

See Polymorphism

haim770
  • 48,394
  • 7
  • 105
  • 133
0

I think you are getting confused with the technicality of the words in the answer.

There are two things here,

  1. Most derived version of the method in context of the derived class being instantiated.

So if you do ,

A a = new B();
a. print(); // this will invoke the method on the class B,
                // since instance of class A has reference to instance of B.

and if you do the following:

A a = new C();
a. print(); // Should call the method on class C, since base class has reference to to the instance of C.

Similarly, a more intuitive way of putting it is:

A a = new A();
a.print(); // this will call the method print in class A irrespective of whether this method was overriden in one of the derived classes.

This is the premises of dynamic polymorphism, wherein, the client can call the method print() on base class object of A without needing to know if A has reference to B or C. The behaviour changes dynamically in client code.

  1. Alternatively, you could also think about most derived version in the following way:

Suppose the method print() was not overriden in C, but was overriden in B, then the most derived version of print() will be in class B. The following snip should be helpful.

class A
{
    public virtual void print()
    {
        Console.WriteLine("A called");
        Console.Read();
    }
}
class B :A
{
    public override void print()
    {
        Console.WriteLine("B called");
        Console.Read();
    }
}
class C : B
{
    public void somerandommethod()
    {
        // some random method not really relevant to this example.
    }
}

static void Main(string[] args)
{
    A a = new C();
    a.print(); // it will now print B (since B has the most derived implementation of print())
}

Hope this answer helps.

Best.

frostedcoder
  • 153
  • 7