Saturday, March 14, 2015

C# vs Java : Method Overriding

When you inherit a class, you inherit its methods. You can alter the behavior of those methods, which is called method overriding. Here's how to override a method in Java:
public class Parent {
   public void fooBar() {
      System.out.println("Parent - fooBar");
   }
}
public class Child extends Parent {

   @Override
   public void fooBar() {
      System.out.println("Child - fooBar");
   }

   public static void main(String[] args) {
      new Parent().fooBar();
      new Child().fooBar();
   }
}
Outputs
Parent - fooBar
Child - fooBar
C#, on the other hand, is a little more complicated. If you tried to do the following in C#...
class Parent {
   public void fooBar() {
      Console.WriteLine("Parent - fooBar");
   }
}
    
class Child : Parent {
   public void fooBar() {
      Console.WriteLine("Child - fooBar");
   }

   public static void Main() {
      new Parent().fooBar();
      new Child().fooBar();
   }
} 
...you'd get a compiler warning similar to the following...
'Child.fooBar()' hides inherited member 'Parent.fooBar()'. 
Use the new keyword if hiding was intended.
It would still produce the same output as the Java version, though.

To override a method in C# you need to use the virtual and override keywords. They may be placed before or after the access modifier.
class Parent {
   virtual public void fooBar() {
      Console.WriteLine("Parent - fooBar");
   }
}
    
class Child : Parent {
   public override void fooBar() {
      Console.WriteLine("Child - fooBar");
   }

   public static void Main() {
      new Parent().fooBar();
      new Child().fooBar();
   }
} 
Outputs
Parent - fooBar
Child - fooBar
So what's the difference between method overriding and method hiding? Let's go back to the original version of the program but this time we'll use the new keyword to suppress the compiler warning.
class Parent {
   public void fooBar() {
      Console.WriteLine("Parent - fooBar");
   }
}
    
class Child : Parent {
   new public void fooBar() {
      Console.WriteLine("Child - fooBar");
   }
} 
We'll also, in the main method, declare a variable of type Parent and instantiate it with a Child object.
public static void Main() {
   Parent p = new Child();
   p.fooBar();
}
Outputs
Parent - fooBar
You'll notice that the Parent's fooBar method is called instead of the Child's. Now let's look at what happens when we override the method.
class Parent {
   virtual public void fooBar() {
      Console.WriteLine("Parent - fooBar");
   }
}
    
class Child : Parent {
   override public void fooBar() {
      Console.WriteLine("Child - fooBar");
   }

   public static void Main() {
      Parent p = new Child();
      p.fooBar();
   }
} 
Outputs
Child - fooBar
This time the Child's fooBar method gets called. It's also the same result we would have gotten if this had been done in Java. In other words, methods in Java are by default virtual. It doesn't hide methods, only overrides them.
   public static void main(String[] args) {
      Parent p = new Child();
      p.fooBar();
   }
Outputs
Child - fooBar
You can prevent a method from being overridden in Java by using the final keyword.
public class Parent {
   final public void fooBar() {
      System.out.println("Parent - fooBar");
   }
}
Because the Parent's fooBar() method is declared as final, when we go to compile the Child class we'll get a compiler error.
fooBar() in Child cannot override fooBar() in Parent
overriden method is final
See Also: Java : The final keyword

To prevent a method from being overridden in C# you use the sealed keyword.
class Parent {
   virtual public void fooBar() {
      Console.WriteLine("Parent - fooBar");
   }
}

class Child : Parent {
   sealed override public void fooBar() {
      Console.WriteLine("Child - fooBar");
   }
}

class GrandChild : Child {
   override public void fooBar() {
      Console.WriteLine("Child - fooBar");
   }  
  
   public static void Main() {
      Console.WriteLine("Press Enter to continue...");
      Console.ReadLine();
   }
}
Because the Child's fooBar method is sealed, the above will result in a compiler error similar to the following:
'GrandChild.fooBar()': cannot override inherited member 'Child.fooBar()' because it is sealed

1 comment:

  1. Thanks for the article. it cleared some confusions i had about overriding

    ReplyDelete