Shadowing Properties ... Good or Bad?

Try this on your own & you can see why even in a VERY simple case shadowing is bad and leads to VERY hard to find bugs :stuck_out_tongue:
CustomSubclass1 and CustomSubClass2 are both subclasses of baseclass. That’s all the set up this requires.
The code, as you can see, is VERY simple.
When you hit the breaks peek at the values in the debugger & variable pane - and scratch your head :slight_smile:

I just did a test and it looks like you can get around this if your shadowed property is a Computed Property and sets the base class directly.

Using your example:

Set
  BaseClass( me ).SomeProperty = value
Get
  return BaseClass( me ).SomeProperty

Any reason not to do it that way?

It’s slightly less fragile but properties, computed or not, are still based on the static type so your computed property will still be ignored by anything using the base class.

I’m not sure what you mean. Using Norman’s example code, where c was set to BaseClass, the value was set properly. I used this code:

  dim c as BaseClass
  
  c = new Sub1
  c.P = 1
  AddToResult Str( c.P )
  
  c = new Sub2
  c.P = 2
  AddToResult Str( c.P )

Output was 1 and 2, as expected.

Where might it not work?

OH, I see what you mean, it’s not going through the computed property. Bad.

Hence Kem you see why shadowing causes weird and often VERY hard to find bugs.

YOU expected it to go through the computed property and if your classes relied on that you’d be tracking down a VERY hard to find “bug”
You see why we constantly tell people “Don’t do this” :stuck_out_tongue:

I wish Xojo officially supported property overriding via computed properties. If there is a clsParent.Visible property we should be able to created a computed property in clsChild and access Super.Visible. clsChild would not have the normal mVisible property in this case. If clsParent already has a computed property, then Super.Visible would call it.

Maybe it would be called something else in the IDE, “Override Property”. With this feature the IDE could block you from creating a shadowed property. If you type an existing property name, just explain the situation and offer to create an override property in a dialog.

On numerous occasions I’ve struggled to work around the fact that we can’t do this, typically when sub classing the framework or 3rd party code. But sometimes in my own code I’ll go back, take code from computed properties, and put it in real methods so that subclasses can properly override it. Or mark a property protected then provide real method accessors so that the child classes can override.

[quote=76445:@Norman Palardy]Hence Kem you see why shadowing causes weird and often VERY hard to find bugs.

YOU expected it to go through the computed property and if your classes relied on that you’d be tracking down a VERY hard to find “bug”
You see why we constantly tell people “Don’t do this” :stuck_out_tongue:
[/quote]

Right, I see that now. This is different behavior than if a subclass overrides a method. In those cases, it always goes through the subclass no matter how the variable is defined, so you might expect a shadowed property to do the same. As demonstrated and explained, it doesn’t.

I guess I could ask, “why allow it at all then?” But I won’t. :slight_smile:

Because people do it and making it an error would break too much code.

See? That’s why I didn’t ask. :wink:

[quote=76447:@Daniel Taylor]I wish Xojo officially supported property overriding via computed properties. If there is a clsParent.Visible property we should be able to created a computed property in clsChild and access Super.Visible. clsChild would not have the normal mVisible property in this case. If clsParent already has a computed property, then Super.Visible would call it.
[/quote]
Get / Set pairs are such a thing - they are virtual.
Properties, computed or not, are NOT virtual.
Make the property private & implement a pair of methods & you’re off to the races.
Consumers of your classes are not aware of any such changes which is really nice as you can move from a public property to computed to get/set pair with no changes required in users of your code.
Few other languages allow you to do this quite as invisibly.

The main beef I have with making computed properties be virtual is that now the framework has to document which properties are computed versus non-computed and it becomes an API contract.

What about ContainerControls?

I add computed properties to a ContainerControl that get/set the properties that I want to modify in the ContainerControl.

Is this ok or is this evil too?

I would like to see the ability to declare an override property regardless of whether or not the parent class has a computed property or just a plain old property, i.e. I basically wish properties were virtual. So there wouldn’t be a need to document computed/non-computed in the framework because Super.Property would access whatever the parent class has. In a sense public properties are already part of an API contract. We just can’t add to their behavior in a subclass.

I realize I’m describing this without any knowledge as to how much work it would require in the Xojo runtime and compiler, and that it may never exist. I’m just pointing out that this is an issue I do run into in Xojo.

That’s the issue. You can’t do that with code you do not control. In that case you have to create Get/Set methods and change code all over the place to use them. But even that can be a problem when there’s additional code you do not control which accesses the property directly.

It’s not an every day thing, but when you run into it…

I’m wincing at the performance impact this would have in terms of up front cost and the cost of missing optimization opportunities…

Would it matter on a modern CPU? I just wrote a quick million loop test and clocked property access at roughly 35,000 microseconds for the entire loop, and method access to the same property at roughly 58,000 microseconds. 23k microseconds divided by a million…there’s no real difference there.

I realize that doesn’t take into account optimization opportunities. But I’ve never perceived a performance difference after renaming/protecting a property and creating accessor methods under the old name.

Even though programs have a ton more resources to eat, performance still matters. I know there are people in the community who are writing physics simulation and they need all the speed they can get. That’s not to say that performance should be the compiler’s only concern, but it is up there when considering language changes this large.

This is under the current compiler, which doesn’t attempt any optimizations. The new compiler will be an optimizing compiler that will be able to do all sorts of clever things.

[quote=76455:@Markus Winter]What about ContainerControls?

I add computed properties to a ContainerControl that get/set the properties that I want to modify in the ContainerControl.

Is this ok or is this evil too?[/quote]
Same problem as noted above
It relies on the static type of the declared variable and not the runtime type
So if you have a container thats a parent for others be VERY careful as you will have the same problems

I use a different name for my new property instead of trying to shadow one & cause myself untold hours of grief

The other thing that making properties virtual may do is introduce new unexpected side effects in existing code - it would just quietly change behavior and thats a bigger problem potentially

Honestly, you would have to convince me with a test case that showed a difference of at least a few seconds, and that would be difficult even in a physics sim. Virtual vs. non-virtual hasn’t been a performance issue in any language since…the 1990’s?

LLVM might miss some optimization opportunities with virtual properties, but it’s going to so radically improve performance to begin with that you’ll still be in the black (if XojoScript is any indication).

Again, while I would like virtual properties, I’m not expecting this feature. Just thinking out loud.

Compiler option :slight_smile:

I’m half joking because one of the nice things about Xojo is that you don’t have to double check 50 compiler options to make sure your code runs correctly (I’m looking at you C/C++/obj.C).