Tuesday, January 15, 2008 3:07 PM
I'm teaching an 'OO with VB.NET' course right now, and last night was the talk about overloading, overriding, and shadowing...specifically around inheritance. Prepping for this showed some interesting behavior that I wasn't aware of, and wanted to share.
Overloading a function or sub means that you have a method with the same name as an existing method. If these are in the same files, then you need to specify different signatures for them. However, you could have a situation where a base class and a derived class both have the same method signatures and method names. In this case, you *don't* have to have different signatures: the compiler is fine with letting you have a derived class with the EXACT method signature as one in your base class.
This is an issue though, because what you're really doing is Shadowing. Where Overriding requires the base class to identify a method as overridable and the derived class to specify that its class is overriding, Shadowing has no such rules. Shadowing clobbers your base class method in favor of the derived class method...and worse yet, this is the default behavior of VB.NET.
So it would appear that Overloading in a derived class and Shadowing are the same thing. Let's say we have two classes:
Class B inherits from Class A. Both have a method called DoSomething( ) in them, and class B overloads that method.
If you created an instance of Class B...
Dim _classB as ClassB
_classB = new ClassB
...and you called DoSomething( ), the method in Class B would execute. If you *didn't* overload that method the same thing would happen. Why? Because the default behavior is to shadow the method.
However...the rules for shadowing change when you're dealing with a variable declared as the base class, but instantiated to a derived class:
Dim _classB as ClassA
_classB = new ClassB
If I were to call the DoSomething( ) method from _classB, it would actually fire off Class A's version of the method, regardless if I overloaded or shadowed the methods in Class B.
So how do you avoid this mess in your code? By being prudent in how you write your methods:
- If you overload a method in a derived class, ensure that it has a different signature than the base class method.
- If you need to overload the method in a derived class with the identical signature from the base class's method, then use the Overridable and Overrides keywords to ensure that the method is picked up properly. This way, even in the second class example, your method from _classB will fire as expected
- Favor composition over inheritance. This is a tried and true phrase: even though you *could* solve a problem by inheriting, see if there's another option that doesn't require you to inherit and compose your object of other helper objects instead.