{"id":25,"date":"2019-05-28T01:29:31","date_gmt":"2019-05-28T01:29:31","guid":{"rendered":"https:\/\/www.great-white-software.com\/blog\/?p=25"},"modified":"2019-06-21T01:44:06","modified_gmt":"2019-06-21T01:44:06","slug":"why-shadowing-should-be-avoided","status":"publish","type":"post","link":"https:\/\/www.great-white-software.com\/blog\/2019\/05\/28\/why-shadowing-should-be-avoided\/","title":{"rendered":"Why shadowing should be avoided"},"content":{"rendered":"\n<p>We&#8217;ll create a sample project to demonstrate why its a bad thing to do.<\/p>\n\n\n\n<p>Start a new desktop project.<\/p>\n\n\n\n<p>Add a new Class that is a subclass of \u201dCancelButton\u201d by dragging a CancelButton from the library to the Navigator.<\/p>\n\n\n\n<p>Name this new class \u201cmyPushButton\u201d<\/p>\n\n\n\n<p>Add a property&nbsp; to it &#8211; enabled as boolean<\/p>\n\n\n\n<p>Make sure the property is public<\/p>\n\n\n\n<p>Now on Window1 add an instance of this new button subclass.<\/p>\n\n\n\n<p>Name it \u201cMyPb\u201d<\/p>\n\n\n\n<p>Now add a bevel button and name it bevTestSubclass.<\/p>\n\n\n\n<p>Change its Caption to say \u201cbevTestSubclass\u201d<\/p>\n\n\n\n<p>In its action event put<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myPb.enabled = Not myPb.enabled\nmyPb.invalidate\n<\/code><\/pre>\n\n\n\n<p>Add a second bevel button and name it bevTestBaseClass<\/p>\n\n\n\n<p>Change its Caption to say \u201cbevTestBaseClass\u201d<\/p>\n\n\n\n<p>In its action put<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PushButton(myPb).enabled = Not PushButton(myPb).enabled\nPushButton(myPb).invalidate\n<\/code><\/pre>\n\n\n\n<p>Save (if you care to) and Run<\/p>\n\n\n\n<p>If you push the bevTestBaseClass button the button enables &amp; disables on each push. And it does this visibly.<\/p>\n\n\n\n<p>But if you click the bevTestSubclass button nothing happens.<\/p>\n\n\n\n<p>Why not ?<\/p>\n\n\n\n<p>Properties are not virtual. Quite literally there are two \u201cenabled\u201d properties and they are not the same one. The custom subclass contains one. And the base class contains one.<\/p>\n\n\n\n<p>So when the code knows you are referring to the subclass type the \u201cEnabled\u201d property that is used is the one in the subclass instance. And the framework doesn\u2019t look at this one at all.<\/p>\n\n\n\n<p>So the framework looks at the one in PushButton and redraws with whatever Enabled state that one says.<\/p>\n\n\n\n<p>And its not the same as the one in the subclass.<\/p>\n\n\n\n<p>But when you press the bevTestBaseClass button you do get the change you expected because the cast makes the code refer to the Superclass version of enabled.<\/p>\n\n\n\n<p>This specific use where a cast is involved isn\u2019t so hard to find with a search and replace. But it\u2019s also not the only way that shadowed properties cause problems. The really tricky ones are where the declared type of a variable is the superclass type and then you get much the same behaviour as with the casts. And this one is NOT easy to find.<\/p>\n\n\n\n<p>We\u2019ll demonstrate by adding additional code to the project so far.<\/p>\n\n\n\n<p>First lets define a new method &#8211; FlipSubClass &#8211; that takes a myPushbutton as a parameter.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Public Sub flipSubclass(button as myPushButton)\n  button.enabled = Not button.enabled\n  button.invalidate\nEnd Sub<\/code><\/pre>\n\n\n\n<p>And for good measure we\u2019ll add a new method &#8211; FlipSuperClass &#8211; that takes a Pushbutton as a parameter<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Public Sub flipSuperClass(button as PushButton)\n  button.enabled = Not button.enabled\n  button.invalidate \nEnd Sub\n<\/code><\/pre>\n\n\n\n<p>The only difference between these two is the type of the parameter.<\/p>\n\n\n\n<p>Now lets add two more bevel buttons to use these new methods.<\/p>\n\n\n\n<p>Add a bevelbutton and name it bevDimSubClass and set the caption to bevDimSubClass.<\/p>\n\n\n\n<p>In this bevel buttons action event put<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  flipSubClass(myPb)\n<\/code><\/pre>\n\n\n\n<p>Add a second bevel button named bevDimSuperClass and set the caption to bevDimSuperClass<\/p>\n\n\n\n<p>And in this action event put<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  flipSuperClass(myPb)\n<\/code><\/pre>\n\n\n\n<p>And run.<\/p>\n\n\n\n<p>Note this time there is NO explicit cast required and we can safely pass a myPushButton to a method that takes a PushButton because a subclass IS always also the super class type (isA would be true if you checked myPb isa PushButton)<\/p>\n\n\n\n<p>And yet the bevDimSubclass button has no effect on the buttons appearance but the bevDimSuperClass button does.<\/p>\n\n\n\n<p>Its the exact same issue as before but this time it\u2019s even harder to detect because what natters here is not the actual type or the instance but the DECLARED type of the parameter.&nbsp;<\/p>\n\n\n\n<p>Since shadowing can cause such hard to track down bugs it better to avoid it.<\/p>\n\n\n\n<p>Now IF you cannot and really to require a subclass have its own \u201cEnabled\u201d property that actually works you should add it as a COMPUTED PROPERTY that in the getter simply casts SELF to the super type and returns the\u2019s supers property value. And in the getter again cast to the super type and set the supers property to that value given.<\/p>\n\n\n\n<p>And <a href=\"http:\/\/great-white-software.com\/gws-rb-samples\/WhyShadowingIsBadAndHowToDoItProperly.xojo_binary_project\">here\u2019s a sample<\/a> that shows the bad version and how to make it work as expected<br><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We&#8217;ll create a sample project to demonstrate why its a bad thing to do. Start a new desktop project. Add a new Class that is a subclass of \u201dCancelButton\u201d by dragging a CancelButton from the library to the Navigator. Name this new class \u201cmyPushButton\u201d Add a property&nbsp; to it &#8211; enabled as boolean Make sure &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.great-white-software.com\/blog\/2019\/05\/28\/why-shadowing-should-be-avoided\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Why shadowing should be avoided&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[2],"class_list":["post-25","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-safe-code"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/posts\/25","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/comments?post=25"}],"version-history":[{"count":4,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/posts\/25\/revisions"}],"predecessor-version":[{"id":152,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/posts\/25\/revisions\/152"}],"wp:attachment":[{"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/media?parent=25"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/categories?post=25"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.great-white-software.com\/blog\/wp-json\/wp\/v2\/tags?post=25"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}