25

So apparently you cannot use the virtual modifier with the override modifier.

virtual - a method that can be overridden

override - a method that is overriding a method of the same name in its parent's class

This leads me to believe that if I override a method in a child class, if that child has a child you can't override that method again.

And it is safe to say that if you put override and virtual in a method declaration you will get a compile error in C#.

However I can't understand why the code I made below works the way in which it does

using System;
public class DrawingObject
{
public virtual void Draw()
{
    Console.WriteLine("Drawing Object");
}
}
public class DrawDemo
{
     public static int Main()
     {
          DrawingObject[] dObj = new DrawingObject[3];


          dObj[0] = new DrawingObject();
           dObj[1] = new Line();
           dObj[2] = new LittleLine();

           foreach (DrawingObject drawObj in dObj)
           {
                drawObj.Draw();
           }
            Console.Read();
           return 0;
       }
  }
 public class Line : DrawingObject
 {
       public override void Draw()
       {// the method above me is in fact virtual because LittleLine overid it?
               Console.WriteLine("I'm a Line.");
       }
  }
  public class LittleLine : Line
  {
       public override void Draw()
       {
              Console.WriteLine("I'm a Little Line.");
         }
    }

Here's the output:

Drawing Object

I'm a Line.

I'm a Little Line.

So the draw method in Line looks as though it was overridden by LittleLine. Is this code not actually overriding it, or is the compiler doing some other trick? Or am I not understanding the context of virtual and override?

Null
  • 1,950
  • 9
  • 30
  • 33
Frank Visaggio
  • 3,642
  • 9
  • 34
  • 71
  • 3
    An `override` method is automatically overridable (`virtual`) again. – H H Jun 28 '12 at 17:51
  • 3
    As others have said, `sealed override` disallows the method to be further overridden in derived classes. Another interesting tidbit: `abstract override` forces the derived classes to override the method. Your class may not provide an overriding implementation of the virtual method of your base class. But, you can force the classes that derive from you to override it. – pnvn Jun 28 '12 at 18:21
  • thanks for clearing that up ! – Frank Visaggio Jun 29 '12 at 15:42

6 Answers6

33

You can declare a certain method as virtual only once, but you can override it as many times as you want - an override is not final, and it does not limit classes that inherit from the first overriding class. The method that will eventually execute is the last one the overrides the virtual method. So your code does behave as expected.

C# is very verbose with regard to overriding - you have more specifiers than C++ or Java. It is so to let the programmer specify the exact intent:

  • You use virtual to specify a method can be overridden by subclasses.
  • You use override to specify you are overriding a method that you know is virtual (if it's not, the compiler will report an error).
  • You use sealed to prevent further overriding.
  • And you use new to hide instead of override.

This can be confusing and sometimes annoying, but it ensures you actually know what you're doing, and it makes your intention self-documented.

Eran
  • 21,632
  • 6
  • 56
  • 89
  • So when draw on the LittleLIne object is called. Does the compiler look at the object see that it has a draw method and call it a day? Or does it look at the littleLine object, see it is a base class of Line, and then see it is a base class of DrawingObject, and start with the root parents method and then go back down the list. – Frank Visaggio Jun 29 '12 at 19:53
  • Ie is there a way to do like a super.draw(), or call the parents method of that object anywhere other then in the class itself? ie doing ((Line)dObj[2]).draw() still calls little lines implementation of draw. Is there anyway to get the parents implementation of the method you overwrote or no – Frank Visaggio Jun 29 '12 at 19:58
  • 1
    @BobSinclar, as far as I know, there's no way of calling an overridden method from the outside (see [this question](http://stackoverflow.com/questions/438939/is-there-any-way-to-call-the-parent-version-of-an-overridden-method-c-net). This might be possible using reflection, but even if it is, it's awkward at best. – Eran Jun 29 '12 at 20:10
  • More knowledge in short summery. :-) Thanks. – Asif Mushtaq Oct 02 '16 at 07:46
4

So apparently you cannot use the virtual modifier with the override modifiers.

Indeed. The method stays virtual unless you override it with a method which is also declared to be sealed. (You can only use the sealed modify on a method when you're overriding something.) From section 10.6.5 of the C# 4 spec:

When an instance method declaration includes a sealed modifier, that method is said to be a sealed method. If an instance method declaration includes the sealed modifier, it must also include the override modifier. Use of the sealed modifier prevents a derived class from further overriding the method.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • http://msdn.microsoft.com/en-us/library/88c54tsw.aspx has a nice write up on using sealed when you override a method – Mr. Graves Jun 28 '12 at 17:56
2

I think you simply misunderstood how virtual works. It's not limited to one level of inheritance, as explained here, for example:

For every virtual method declared in or inherited by a class, there exists a most derived implementation of the method with respect to that class. The most derived implementation of a virtual method M with respect to a class R is determined as follows:
•If R contains the introducing virtual declaration of M, then this is the most derived implementation of M.
•Otherwise, if R contains an override of M, then this is the most derived implementation of M.
•Otherwise, the most derived implementation of M with respect to R is the same as the most derived implementation of M with respect to the direct base class of R.

YavgenyP
  • 2,113
  • 14
  • 11
2

This behavior is right. If you don't want inherited class to override your virtual method, you can mark it "sealed" like this:

public class Line : DrawingObject
 {
       public sealed override void Draw()
       {
               Console.WriteLine("I'm a Line.");
       }
  }

After that LittleLine class won't be able to override Draw method.

1

virtual means your method is dispatched through a virtual method table. If a method's virtual, any reference to that method on a derived class has to go through the vtable. You can't non-virtualize it just because a derived class overrides it - what would happen if LittleLine was cast to DrawingObject? You still need to find the correct implementation, which wouldn't be DrawingObject's

MNGwinn
  • 2,394
  • 17
  • 18
1

It looks like it worked as intended.

dObj[0] = new DrawingObject();
dObj[1] = new Line();
dObj[2] = new LittleLine();

You're calling Draw() and in a loop

heres the output Drawing Object I'm a Line. I'm a Little Line

dObj[0].Draw() -> "Drawing Object" dObj[1].Draw() -> "I'm a Line." dObj[2].Draw() -> "I'm a Little Line"

So The draw method in Line looks as though it was Overrriden by LittleLine

Yes, isn't that what you expected? The method was marked as Virtual at the base class and you've overridden it. If you want to 'add to it' you'll need to use some other pattern. A decorator perhaps.

Mr. Graves
  • 452
  • 4
  • 11