Compiler confusion with using Shadows keyword

F

flat_ross

For anyone who is just getting into VB.NET and/or is starting to work
with inheritance I would like to point out a potential pitfall. We
found this confusion recently when code-reviewing an application. If
you have not used the keyword 'Overridable' then read on for sure...

If you setup a child class and you want to override a method in your
base class, you may see the squiggles under your child's method name.
The pop-up/build error says something like:
C:\Projects\TestShadows\Ball.vb(28): function 'GetMessage' conflicts
with function 'GetMessage' in the base class 'BaseClass' and so should
be declared 'Shadows'.

To fix this, you may go ahead and put the 'Shadows' keyword into your
function declaration and, voila, it works. You run your project and
the overriden (so you think) method fires perfectly.

Unfortunately, this 'Shadows' keyword does not truly provide
inheritance (in my opinion). If you decide to get into polymorphism
then you'll quickly see the problem. If you have an instance of your
child class stored in a datatype defined as your base class and then
call the 'Shadowed' method, then the instance will actually call the
base class' method and not your 'Shadowed' method. I would hazard a
guess that if you are just starting out then this is not the
functionality you would expect. I would assume that you'd expect the
'Shadowed' method. I am not sure what other code situations would
highlight this discrepancy; maybe this is the only one so if you never
plan to do it then you'll never have a problem. But I've learned never
say never...

To fix this, the proper way to setup methods for inheritance is to
setup the base class' method with the keyword 'Overridable' and then
setup the child's method as 'Overrides'.

An explanation of 'Shadowing' is in the VS2003 help:
ms-help://MS.VSCC.2003/MS.MSDNQTR.2004APR.1033/vbcn7/html/vbconShadowing.htm.
If you can't find this file then click on F1 while your cursor is over
the Shadow keyword. Once help is up, scroll down and click the
'Shadowing' link under See Also. Even though it gives an in-depth
discussion on the concept it reads like it was written by a lawyer.
Only until I wrote up some demo code was I able to see the
ramifications.

I guess there are situations where Shadows may be of use but I think
it just confuses the situation (although again, never say never). The
only example I can think of is if you were upgrading the base class
and wanted to protect the child class' interface. But then you'd
probably have a good idea of what implications Shadowing has and your
object-oriented design would key in on that. Although I'm no OO
expert, I have no idea where Shadowing fits into the design anyway. I
would think designing Interfaces would come into play way long before
Shadowing.

Bottom line is I just wanted to point out that you may be incorrectly
using Shadows where you should be using Overridable/Overrides. I think
the compiler should have been designed to suggest using
Overridable/Overrides before ever suggesting Shadows.

Following is a code sample I used to demo the issue:

1) Create a web or win project, my example is a web project.
2) Add a class file to the project.
3) Make sure the new class file is empty and paste this content:
Public Class BaseClass
Public Overridable Function GetMessage() As String
Return "In BaseClass."
End Function
End Class

Public Class ShadowsMethod
Inherits BaseClass

Public Shadows Function GetMessage() As String
Return "In ShadowingMethodClass."
End Function
End Class

Public Class OverridesMethod
Inherits BaseClass

Public Overrides Function GetMessage() As String
Return "In OverridesMethod."
End Function
End Class

4) This code is for the page_load of a web form. If you want to use a
winform, you'll have to modify the Response.Writes to methods that
write to something on a winform (textbox, listbox, label, etc.)
Dim oInherits As New OverridesMethod
Dim oShadows As New ShadowsMethod
Dim oBase As BaseClass

'Call child's GetMessage
Response.Write(oShadows.GetMessage)

'Assign Child instance to a base datatype
oBase = oShadows

Response.Write("<br>Call method on derived class stored in
BaseClass datatype: ")
Response.Write(oBase.GetMessage & "<i><-- Because of
shadowing, the derived class' method is not called when it is assigned
to a BaseClass variable. Instead the base class' method is
called.</i>")
Response.Write("<br>--------------<br>")



'Call child's GetMessage
Response.Write(oInherits.GetMessage)

'Assign Child instance to a base datatype
oBase = oInherits

Response.Write("<br>Call method on derived class stored in
BaseClass datatype, ")
Response.Write(oBase.GetMessage & "<i><-- Because of
overriding, the derived class' method is called even when it is
assigned to a BaseClass variable.</i>")
Response.Write("<br>")
 
S

SStory

Good point...
I think Shadows was somehow meant to allow you to override what the designer
didn't want you to override but not change the class for real--which is the
effect you are experiencing....

Shane
 
G

Greg Burns

I always found Shadows keyword confusing too.

Most books touch on the topic you are bringing up and tell you to beware
when using Shadows.

Programming VB.NET: A Guide For Experienced Programmers puts it this way:
"If you use the Shadows keyword, members of objects get called by the kind
of container the object is stored in, not by what their ultimate types are."

I too would like to hear more about when Shadowing should and should not be
used.

Greg
 
S

SStory

It seems to me sort of a kludgy way to force a class to do something that
the class designer didn't want to allow-but only for the next generation and
not further generations....so I guess it would have an immediate benefit in
that case...but not if you want to continue down the inheritance chain with
the class you derive and use shadows in.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top