Shadowing Properties ... Good or Bad?

In an attempt to make things more consistent when dealing with what I believe should be default value assignments for controls (Shell.Timeout and Label.Transparent on Windows, for example), I create new subclassed controls and then add the default property values to the new versions.

When I analyze the code, the analysis always reports the shadowed values.

1: Is this OK (it seems to be)?
2: is there a better way?

[quote=76232:@Tim Jones]In an attempt to make things more consistent when dealing with what I believe should be default value assignments for controls (Shell.Timeout and Label.Transparent on Windows, for example), I create new subclassed controls and then add the default property values to the new versions.

When I analyze the code, the analysis always reports the shadowed values.

1: Is this OK (it seems to be)?[/quote]

No, please don’t shadow properties. It makes it such that myShell.Timeout isn’t the same as Shell(myShell).Timeout, which will likely bite you at some point in the future.

Okay, so is there an answer for #2? :slight_smile: Is there a better way?

I’m really frustrated that I must go through every shell and label instance and set the obvious defaults for Windows. One of my projects has over 380 labels … and you guys all know how shell-crazy I am.

One tip is to make your labels into a control set so you only have to set the property once per Window.

That would have helped 5 years ago. Now it’s much more work to array them and change associated code as to change the property values :frowning:

Couldn’t you just set the properties the way you want in the Open event handler of your subclass?

Class MySpecialLabel > Label Sub Open() me.text = "Some Default Value" Open() //Call the open event, Assuming you allow access to the open event. End Sub End Class

Something to that effect =)

Shadowing properties is evil, and I want to thank Xojo for generating a compiler warning.

Could you explain why? In VB .NET there is even a keyword for it.

Simply because it usually just happens by accident, and it is very easy to not realize that the property is in fact shadowed (because you forgot that you already created the property in the super class) and introduce bugs which are hard to track down. Maybe the keyword in VB.Net helps prevent doing this accidentally. And in general I find it hard to come up with a scenario where shadowed properties are the best way to tackle a problem. But that might just be me.

Shadowing by accident? How can that happen? If you create a subclass and want to shadow a property, you know it (plus you need to cast Self properly) - hardly something that can happen by accident.

This depends on the documentation - if written properly, there won’t be a problem. By the way, by overriding a method in a subclass the same can happen when the developer of the subclass writes code which contradicts the code of the super class.

Since properties can’t be overridden, one can use shadowing to mimic overriding.

[quote=76258:@Eric Hoaglin]Class MySpecialLabel > Label Sub Open() me.Transparent = True Open() //Call the open event, Assuming you allow access to the open event. End Sub End Class[/quote]
That’s the answer for getting rid of the warning, but it seems inelegant compared to shadowing the property to set its value.

Except that I can find no call for using your example in any code that I write. I can see this when dealing with a Window or a Container, but when I’m dealing with a Shell instance, it is short term (within a method) and is only in scope for the called instance. When I access a label, it is only to change its text for a specific instance. I can’t find a situation when shadowing properties In my subclass would cause unexpected behavior.

You can make a Label subclass with your default values using the ‘Inspector Behavior’. No code needed, no shadowed properties. You’ll need to get in the habit of dragging your class into the window though.

For a Shell you can set the default Timeout in the Inspector too. But you say that you typically make Shells in a method then toss them. So why not just have the subclasses constructor set the Timeout value? Actually, I’m not clear how shadowed properties are supposed to help these situations:)

While that would apply to Labels, it wouldn’t help the Shell example. And, using the Constructor is no less effort than using the Open event.

Of course, the true answer is to get the most useful defaults actually set as defaults in the standard class.

feedback://showreport?report_id=25954
feedback://showreport?report_id=32971 (sorry about the typos, it’s 3:55AM here…)

Joes example
You have no idea how many bug reports we get that are the result of shadowing

Create a TextField subclass and shadow the Text property.
Place and instance into a window.
In the window.Open event place this code:

[code] ShadowTextField1.text = “Test”

dim myFieldText as string

for i as integer = 0 to self.controlCount-1
if self.control(i) isA TextField then
myFieldText = TextField(control(i)).text
end if
next
break[/code]

Guess what contains myFieldText property?

[quote=76417:@Massimo Valle]Create a TextField subclass and shadow the Text property.
Place and instance into a window.
In the window.Open event place this code:

[code] ShadowTextField1.text = “Test”

dim myFieldText as string

for i as integer = 0 to self.controlCount-1
if self.control(i) isA TextField then
myFieldText = TextField(control(i)).text
end if
next
break[/code]

Guess what contains myFieldText property?[/quote]
A Perfect example of why I only use StaticText, ne Label arrays for absolutely static text. If it’s something that I might change, it gets a real name.

Interesting. Maybe because there is no documentation on it?

This is Joe’s example…

… but this is not an explanation (no offense):

Why, what is the difference to shadowing in other languages and what is the difference to overriding a method? I mean for the programmer using the class, not compiler-wise. For example, if you override myShell.Close() in the myShell subclass, it is not the same as Shell(myShell).Close() either.

We generally try to document things that are good to do - not ones that will help you cause yourself grief.

Methods are virtual - properties are not.

Shadowing properties - well … I’ll let joe detail that one lest I make an error about it

Fair, my point was that property access is based on the static type of the expression. It’s unlikely that anyone would be typing that cast directly (unless they are trying to dig themselves out of a hole they created by shadowing), but it is likely that other places will treat it as Shell and not the the custom subclass. For example, Shell’s own Execute method will see the static type as Shell and will select a different version of the shadowed Timeout property than what your code would.

Most other languages I can think of off the top of my head (C++, Java, Objective-C) behave the same in terms of shadowing with the solution being to have accessor methods that can be overridden. I’m not sure what you’re getting at differentiating between the ‘programmer using the class’ and ‘compiler-wise’.

Actually, it is. Both invoke the overridden method and not Shell’s Close method.