Comparison of Method Overriding and Hiding in C# and Java

Most people who read technical articles are familiar with method overriding. However, Method Hiding is less common. This discussion will primarily focus on C#, as Java doesn’t seem to have a way to hide instance methods. This will be discussed further at the end.

Method Hiding occurs when a method in a derived class has the same signature as a method in the base class, but doesn’t override the base (virtual) method. To avoid a compiler warning, use the “new” keyword when declaring the method in the derived class. This indicates an intention to hide the parent method.

Here are some situations where method hiding might be used:

  • Non-Virtual Method in the Base Class: If a non-virtual method in the base class needs different behavior in the child class, you can hide it. In this scenario, the method call is determined at compile time, not runtime. There’s no involvement of the vTable. The type of the variable used to invoke the method determines which method is called. This is static dispatch.
  • Virtual Method in the Base Class: Declaring a method with the same signature in the child class using “new” instead of “override” disrupts polymorphism. If the method is invoked using a variable of the parent type, the parent’s method is called. This is because the vTable entry for the child class points to the parent’s method. However, when invoking the method using a variable of the child type, the compiler directly calls the child’s method without using the vTable.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
public class Animal{
  
 public virtual void Walk(){
  Console.WriteLine("Animal::walk");
 }
}

public class Person: Animal{
 
 public new void Walk(){
  Console.WriteLine("Person::walk");
 }
}

  Animal a1 = new Person();
  //prints Animal::Walk, so the the walk slot in Person's vTable points to the parent's method
  a1.Walk();
  
  Person p1 = new Person();
  //no vTable involved here, it just prints Person::Walk
  p1.Walk();

```*   **Virtual New Combination:** Using both "virtual" and "new" when declaring the method in the derived class disrupts the polymorphism chain up to that point and starts a new one.
    
    ```
    public class Animal{
     public virtual void Run(){
      Console.WriteLine("Animal::Run");
     }
    }
    
    public class Person: Animal{
     public virtual new void Run(){
      Console.WriteLine("Person::Run");
     }
    }
    
    public class Employee: Person{
     public override void Run(){
      Console.WriteLine("Employee::Run");
     }
    }
     
      a1 = new Animal();
      a1.Run();
      a1 = new Person();
      //prints Animal::Run, so the vTable slot for Person points to the parent one
      a1.Run();
      
      p1 = new Person();
      //prints Person::Run, so it seems like there's a second slot in the vTable
      p1.Run();
      
      //polymorphism works fine using that second slot, both methods write Employee::Run
      p1 = new Employee();
      p1.Run();
      Employee e1 = new Employee();
      e1.Run();
     
     }
    }
    
    ```In this scenario, the Person class appears to have two slots in its vTable: one for Animal::Run and another for Person::Run. The slot used at invocation time depends on the type of variable referencing the instance.

You can find more details about this at [get the source here](http://www.telecable.es/personales/covam1/deployToNenyures/SourceCode/MethodHiding.cs)

Now, the question is: **Is Method Hiding actually useful?** It's worth noting that Java seems to avoid this feature.  Besides [the one explained here](http://stackoverflow.com/questions/2663274/is-method-hiding-ever-a-good-idea), which involves working around the lack of return type covariance in C# (a feature that Java has), it's hard to justify its use.  There may be some limited use in the first case described above. If a method wasn't declared virtual and you need to modify its behavior in a derived class, hiding it might seem like a solution. However, this could be risky. The decision to not declare the method as virtual might have been intentional, and using method hiding could violate the design principles of the base class.

In cases 2 and 3, it's unclear why method hiding would be necessary. It's debatable whether this feature in C# is beneficial or not. It offers flexibility but can also lead to increased complexity and unexpected behavior.

To wrap up, let's compare how C# and Java handle method overriding and hiding.

*   **Default Virtual Behavior**: Java methods are virtual by default, while C# methods are not. Coming from dynamic languages, the Java approach seems preferable. Dynamic dispatch is generally preferred.
*   **Final Keyword**: Using the "final" keyword on a method in a derived Java class behaves differently than C#'s "new" keyword. It doesn't break polymorphism; instead, it prevents further overriding by derived classes. The new method is added to the corresponding vTable slot.

public class Animal{ public void walk(){ System.out.println(“Animal::walk”); } }

public class Person extends Animal{ public final void walk(){ System.out.println(“Person::walk”); } }

Animal a1 = new Person(); //prints Person::walk, so even when declared final in the child, this method seems to be added to the slot in the //Child vTable a1.walk();

1
2
3


[There's not an equivalent to "new" in Java](http://stackoverflow.com/questions/1125269/new-modifier-in-java)
Licensed under CC BY-NC-SA 4.0
Last updated on Jan 28, 2023 07:15 +0100