7.10 Method overriding using the virtual and override Modifiers


7.10 Method overriding using the virtual and override Modifiers

There are some significant differences here between Java and C#. Method overriding in C# involves two keywords borrowed from C++ with no equivalents in Java “ virtual and override . Take note of them carefully .

Like Java

  • Private methods in the superclass cannot be overridden in a subclass. If a subclass has a method of the same signature as a private method in the superclass, this is not considered to be a method override. [12]

    [12] Take note that if a method is declared as private in the superclass, and there is a method of the same signature ( name and parameters only “ the method signature excludes the return type) in the subclass, this does not constitute 'method overriding'. The reason is that private methods are not visible to subclasses anyway, and hence cannot be overridden. I am bringing this out here because in your experiments you may declare a method without any access modifier (remember that in C#, default accessibility is private) in the superclass without using the virtual keyword. When you write a method of the same signature in the subclass and compile it, there will be no warnings or errors at all. C#'s method overriding rules still apply “ it's just that you are not performing method overriding in this case.

  • You can invoke the superclass's method, which has been overwritten in the subclass, by using the C# keyword base “ this is similar to Java's super keyword. Here is an example.

     1: using System;  2:  3: class Child:Parent{ // Child extends Parent  4:   public static void Main(){  5:     new Child().DoThis();  6:   }  7:   public override void DoThis(){  8:     Console.WriteLine("DoThis of child");  9:  base.DoThis()  ; 10:   } 11: } 12: 13: class Parent{ 14:   public virtual void DoThis(){ 15:     Console.WriteLine("DoThis of parent"); 16:   } 17: } 

    Output:

     c:\expt>test DoThis of child DoThis of parent 

Unlike Java

  • If you want to override a method in C#, you need to declare the method which is intended to be overridden using the virtual keyword in the superclass. You have to declare the overriding method with the override keyword in the subclass.

    In Java, You override a method like this:

     1: // Child.java  2: public class Child extends Parent{  3:   public static void main(String args[]){  4:     new Child().doSomething();  5:   }  6:  void doSomething()  { // no special keyword  7:     System.out.println("running Child's version");  8:   }  9: } 10: 11: class Parent{ 12:  void doSomething()  { // no special keyword 13:     System.out.println("running Parent's version"); 14:   } 15: } 

    Output:

     c:\expt>java Child running Child's version 

    If you want to override a method in C#, you must use the virtual and override keywords. A method in the superclass to be overridden must be declared as a virtual method. A method which is overriding a virtual method must be declared as an override method. A non-virtual method (methods are non-virtual by default) cannot be overridden. [13]

    [13] Without the virtual and override keywords, C# does what is similar to 'early binding'. During compilation into MSIL, C# relates a call to an overridden method in any subclass to a jump to the superclass's version of the method. In a virtual method invocation, the runtime type of the instance for which the invocation takes place determines the actual method implementation to invoke. In a non-virtual method invocation, the compile-time type of the instance is the determining factor.

    This is the correct way to do it using the virtual and override keywords in C#:

     1: using System;  2: public class Child:Parent{  3:   public static void Main(){  4:     new Child().DoSomething();  5:   }  6:   public  override  void DoSomething(){  7:     Console.WriteLine("running Child's version");  8:   }  9: } 10: 11: public class Parent{ 12:   public  virtual  void DoSomething(){ 13:     Console.WriteLine("running Parent's version"); 14:   } 15: } 
  • For Java, an overriding method can have weaker (less strict) accessibility than the overridden method. The following code compiles and works in Java.

     1: // Child.java  2: public class Child extends Parent{  3:   public static void main(String args[]){  4:     new Child().doSomething();  5:   }  6:  public  void doSomething(){  7:     System.out.println("running Child's version");  8:    }  9: } 10: 11: class Parent{ 12:  protected  void doSomething(){ 13:     System.out.println("running Parent's version"); 14:   } 15: } 

    However, C# insists that the overriding method must have the same accessibility as the overridden method. Examine the following C# class and its corresponding compilation error.

     1: using System;  2: public class Child:Parent{  3:   public static void Main(){  4:     Child c = new Child();  5:     c.DoSomething();  6:   }  7:  public  override void DoSomething(){  8:     Console.WriteLine("running Child's version");  9:   } 10: } 11: 12: public class Parent{ 13:  protected  virtual void DoSomething(){ 14:     Console.WriteLine("running Parent's version"); 15:   } 16: } 

    Compilation error:

     Source1.cs(7,24): error CS0507: 'Child.DoSomething()': cannot change access modifiers when overriding 'protected' inherited member 'Parent.DoSomething()' 

Additional notes on virtual methods

  • By default (if you do not declare a method with the virtual keyword), methods are non-virtual, and non-virtual methods cannot be overridden.

  • Although a virtual method can be overridden, it doesn't have to be. It doesn't matter if a virtual method is not overridden in a subclass “ it will be inherited by the subclass and can be invoked normally just like other inherited non-virtual methods.

  • A virtual method cannot be declared with the following keywords “ static , abstract , or override .

    - Abstract methods are implicitly virtual (they must be overridden in a subclass before they can of use), but you cannot declare a method using both the abstract and virtual modifiers (this results in a compilation error). Just declare an abstract method with the abstract modifier alone.

    - Although an overriding method cannot have the virtual modifier, a method declared with the override modifier is 'automatically virtual' (in a sense) and you can still override that method in a future subclass.

  • Virtual methods cannot be declared as private. [14]

    [14] This follows logically “ a private method is not visible in a subclass, and a virtual method is meant to be visible so that it can be overridden. So, a virtual private method simply doesn't make any sense.

  • If you come across the term 'most derived method', it refers to what the name implies. A virtual method can be overridden in a subclass, which in turn can be overridden by another subclass, and so forth. The most derived method is the 'latest overridden version' in the subclass lowest in the hierarchy which has this method implemented.

Method hiding versus method overriding

Try something like this in C# without the virtual and override keywords (which looks like method overriding in Java):

 1: using System;  2: public class Child:Parent{  3:   public static void Main(){  4:     new Child().DoSomething();  5:   }  6:  public void DoSomething()  { // override not used  7:     Console.WriteLine("running Child's version");  9: } 10: 11: public class Parent{ 12:  public void DoSomething()  { // virtual not used 13:     Console.WriteLine("running Parent's version"); 14:   } 15: } 

A compilation warning appears, but the assembly file is still created:

[View full width]
 
[View full width]
Test.cs(5,15): warning CS0108: The keyword new is required on 'Child.DoSomething()' graphics/ccc.gif because it hides inherited member 'Parent.DoSomething()'

The resultant EXE runs as expected too:

 c:\expt>test running Child's version 

It may seem that the DoSomething method has been successfully overridden in the subclass despite a warning message. Far from being a discrepancy between the C# standard and the behavior of the C# compiler, [15] you are actually doing something called method hiding here, rather than method overriding (see section 7.11).

[15] Initially I thought that this behavior was due to a bug in my C# compiler. I have never heard of 'method hiding' in all my years as a Java developer!



From Java to C#. A Developers Guide
From Java to C#: A Developers Guide
ISBN: 0321136225
EAN: 2147483647
Year: 2003
Pages: 221
Authors: Heng Ngee Mok

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net