Sunday, June 6, 2010

Override non-virtual (nonoverridable in vb.net) methods

You might wonder if there is a possibility to override nonvirtual or nonoverridable (vb.net) methods. Suppose you are using a third party software then you may need to override some of its methods which are not declared as virtual, this is also a likely requirement when you are writing a wrapper to some existing controls/software/functionality.
This is actually not overriding the actual function but it is called hiding the base class implementation and this can be implemented as following

vb.net implementation:


 Class myBaseClass
        Public Function MyNonOverridableMethod() As String
            Return "I am not overridable"
        End Function

    End Class

    Class myDerivedClass
        Inherits myBaseClass
        Public Shadows Function MyNonOverridableMethod() As String
            Return "I overrode my base class function"
        End Function

    End Class

Note that I have used keyword "shadows" here, which tells the runtime that these two functions are separate implementations (not correlated) in their respective classes.

now when I call them from Main


Sub Main()
        Dim b As myBaseClass = New myDerivedClass()
        Console.WriteLine(b.MyNonOverridableMethod())

        Dim d As myDerivedClass = New myDerivedClass()
        Console.WriteLine(d.MyNonOverridableMethod())

        Console.ReadLine()

    End Sub

This will print me
"I am not overridable"
"I overrode my base class function"

you can see, that this is still using runtime polymorphism, on runtime it sees that the function being called is not virtual so it has to be called from variable reference type (not the type of the object got created). Has the function being declared virtual, runtime will call it from the type of the object that has been created but not from the type of the reference pointer it is holding.(in case of base class function being declared virtual/nonoverridable and derived class overriding it, the previous example would always be printing "I overrode my base class function").

C# implementation for same:


public class myBaseClass
 {
  public string MyNonOverridableMethod()
  {
   return "I am not overridable";
  }

 }

 public class myDerivedClass : myBaseClass
 {
  public new string MyNonOverridableMethod()
  {
   return "I overrode my base class function";
  }

 }
The only difference is that "Shadows" keyword is replaced by "New".
calling from Main will reproduce the same result.


public static void Main()
11    {
12        
        myBaseClass b = new myDerivedClass();
14        Console.WriteLine(b.MyNonOverridableMethod());
15
16        myDerivedClass d = new myDerivedClass();
17        Console.WriteLine(d.MyNonOverridableMethod());
18
19        Console.ReadLine();
20
21    }
22

2 comments:

  1. Method hiding is for exactly those times when you need to have two things to have the same name but different behavior, otherwise it should not be used.
    Real world example -
    abstract class Food {
    public decimal TaxRate { get { return 7.0m;} }
    }
    abstract class Grocery : Food {
    new public decimal TaxRate { get { return 0.0m; } }
    }
    class Cake : Grocery {
    new public decimal TaxRate { get { return 7.0m; } }
    }

    Above example is not designed very well but there can not be better name than "TaxRate" in this example.On the top of that assume abstract Food class is in 3rd party dll and you are required to use it but can not modify the method name.

    ReplyDelete
  2. You are right. Generally if the author of the class thinks that someone can use my class but may give different behavior, he would prefer to declare those methods (behavior) as virtual and let any derived class give that its own desired implementation.
    That means if something is not marked virtual (overridable in vb.net) it has the implicit assumption that behavior needs to be intact with the usage of the class.
    Hiding base class function implementation as mentioned in the article is not a good practice but comes handy when you desperately want to change the behaviors. Ideally in these scenarios one should consult with the author and try to walk into his shoes and understand the reason for not making method overridable/virtual.

    ReplyDelete