As the class I'm teaching moves into OO topics, inevitably the subject of “Shadows” and “Overrides” comes up. “Shadows” probably wins the award as the oddest sounding addition to the VB language courtesy of .Net . . . although there is some strong competition from AndAlso and OrElse. If you want more on this topic, check out this good MSDN piece on Shadows.
When you’re implementing behaviour in a VB.Net class that’s derived from a base class, you have two options: Shadowing or Overriding.
To use Overrides in the derived class, the base class member you’re changing (or replacing) must be declared as Overridable. This means that if the base class designer doesn’t have the foresight to flag the member as Overridable you can’t use Overrides in the derived class. I suppose an organization could require every method to include the Overridable modifier before you compile and deploy the code, but that doesn’t seem like a good idea to me for security and other reasons. My point is, it’s impossible for the base class developer to anticipate future needs to adjust an object’s behaviour in a derived class.
Enter the “Shadows” keyword.
The Shadows modifier comes into play when the base class HASN’T been flagged as Overridable. You can replace any base class method with the Shadows modifier – but recognize that Shadows completely replaces the base class method without regard to method signature.
If this was all there was to it, this blog wouldn’t be necessary. The issue grows more complicated because you can use Shadows when a method is marked as Overridable, begging the question: what impact does Shadows and Overrides have on my object’s behaviour?
The short answer: when working with an object polymorphically, Shadows promotes the variable over the type, while Overrides promotes the type over the variable.
Yikes, how’s that for a short answer? An example will shed more light on this; consider the following class structure.
Public Class IcedTea
Inherits Drink
Public Shadows Function Consume() as String
return "Consuming iced tea"
End Function
End Class
Public Class Drink
Public Function Consume() as String
return "Consuming a Drink"
End Function
End Class
Public Class AlphaRomeo
inherits Car
Public Overrides Function Drive() as string
Return "Driving an Alpha Romeo"
End Function
End Class
Public Class Car
Public Overridable Function Drive() as String
Return "Driving a Car"
End Function
End Class
These are two contrived examples of base and derived classes; the Car:AlphaRomeo example uses Overrides; the Drink:IcedTea example uses Shadows in the derived class and nothing special in the base class. Let’s use this test harness to see these classes at work:
dim objCar as New Car()
ListBox1.Items.Add( objCar.Drive() )
dim objAlpha as New AlphaRomeo()
ListBox1.Items.Add( objAlpha.Drive() )
objCar = objAlpha
ListBox1.Items.Add( objCar.Drive() )
Listbox1.Items.Add( "---------------------------" )
dim objDrink as New Drink()
ListBox1.Items.Add( objDrink.Consume() )
dim objTea as New IcedTea()
ListBox1.Items.Add( objTea.Consume() )
objDrink = objTea
ListBox1.Items.Add( objDrink.Consume() )
If you place this code in a button click event and run it, you’ll notice the Car:AlphRomeo example shows the “Type over Variable” behaviour. Even though the variable is defined as a Car type, when it contains an AlphaRomeo type it uses the AlphaRomeo method. The opposite is the case with the Drink:IcedTea example, it shows “Variable over Type” behaviour. When the objDrink variable contains an IcedTea instance, the variable’s method takes precendence over the type. This is just the opposite of the Overrides modifier and clarifies the short answer: when working with an object polymorphically, Shadows promotes the variable over the type, while Overrides promotes the type over the variable.
I think the Overrides behaviour is generally more desirable for object models and polymorphic processing (if I call drive on all the objects in a Car collection, I tend to want the AlphaRomeos to process their Drive() method and the regular Cars to process their Drive() method). There are cases, however, where the Shadows modifier might be appropriate; if a method isn’t flagged as Overridable, of course, you don’t have any choice and have to go with Shadows. Make an informed decision and know that Shadows promotes the variable over the type.
Sorry for this but I can’t help it . . . another lesson we can draw from this is that if you’re driving a car and drinking, make sure it’s only iced tea!
Happy .Netting.