{"id":825,"date":"2011-11-09T09:15:26","date_gmt":"2011-11-08T21:15:26","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=825"},"modified":"2011-11-09T09:18:38","modified_gmt":"2011-11-08T21:18:38","slug":"class-helpers-a-hackers-cloak-of-respectability","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/825\/","title":{"rendered":"Class Helpers &#8211; A Hackers Cloak of Respectability"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p><a href=\"http:\/\/blogs.embarcadero.com\/mathewd\/2011\/11\/08\/gaining-access-to-private-fields-of-a-class\/\">Mat DeLong just posted another great example of when not to abuse class helpers in Delphi<\/a> (though I should add that he didn&#8217;t seem to see it that way).  \ud83d\ude42<\/p>\n<p>But you don&#8217;t need helpers to do what this technique achieves, and in my view you really shouldn&#8217;t be using helpers for it in the first place.<br \/>\n<!--more--><\/p>\n<p>When hacking around in ways that you really shouldn&#8217;t, dressing it up in the respectability of a (mis-used) language feature is asking for trouble.  Not to mention that once you introduce a helper you must forever live with your fingers crossed that you don&#8217;t have in, or in the future happen to bring into, scope some other helper for the target class (and indeed that any 3rd party code you use now or in the future doesn&#8217;t do likewise).<\/p>\n<p>I also believe this is almost certainly a bug in helpers as you should surely only have access to protected members from a helper, not private and certainly not strict private.  Or so I would have thought and expected.  Bizarrely this expectation <em>is<\/em> seemingly reflected in the <em>Code Completion<\/em> suggestions when referencing &#8220;Self&#8221; in a helper implementation, but is not enforced by the compiler.<\/p>\n<p>Very odd.  But perhaps cross some other fingers against the day that this bug &#8211; if such it is &#8211; is fixed.  Just in case.<\/p>\n<p>However, there is an alternative that doesn&#8217;t rely on mis-appropriating language features.<\/p>\n<p>We have always (since <strong>Delphi 1<\/strong>!!) been able to reach private members of other classes by simply creating an overlay class and type-casting.  Using Mat&#8217;s example, to gain access to the <strong>fComponentList<\/strong> member of a <strong>TDSCustomServer<\/strong>:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n    TDSCustomServerCracker = class abstract(TComponent)\r\n    \/\/ :begin DSCustomServer member decls:\r\n    protected\r\n      FDbxContext: TDBXContext;\r\n    private\r\n      FStarted: Boolean;\r\n      FConfig: TDSConfiguration;\r\n      FServerMethodProvider: TDSServerMethodProvider;\r\n      FComponentList: TDBXArrayList;\r\n      FHideDSAdmin: Boolean;\r\n    \/\/ :end DSCustomServer decl\r\n\r\n    \/\/ Expose private members with some additional property declarations\r\n    public\r\n      property ComponentList: TDBXArrayList read fComponentList;\r\n    end;\r\n<\/pre>\n<p>Now in your code, when you need to dig inside a DSComponent, hard-cast using your cracker class:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  theList := TDSCustomServerCracker(someServer).ComponentList; \r\n<\/pre>\n<p>This works because your &#8220;fake&#8221; cracker class has the same layout in memory of its declared instance data, so you can use your cracker class to expose the instance data of some other class instance by hard casting.<\/p>\n<p>Yes, this is more work and yes it&#8217;s much, <em>much<\/em> nastier.  But what we are doing here <strong>is<\/strong> nasty.  In my experience, as uncomfortable as it may make us feel, it is far better to be open and honest about hack-o-logy when we have to resort to it.  Tarting it up and casting a veil of respectability over our misdeeds is just a pretense; a sop to our own ego&#8217;s (&#8220;I&#8217;m a professional developer, not a hacker!&#8221;).<\/p>\n<p>Writing such code that draws attention to itself by laying it&#8217;s hackology out for all to see is absolutely the way to go in my view.  Your future self will thank you, if no one else.  \ud83d\ude42<\/p>\n<p>But over and above all of that, this also has the added advantage of being able to happily co-exist with any <strong>legitimate<\/strong> &#8220;helper&#8221; that is in scope (or is brought into scope in the future).<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">2<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> Mat DeLong just posted another great example of when not to abuse class helpers in Delphi (though I should add that he didn&#8217;t seem to see it that way). \ud83d\ude42 But you don&#8217;t need helpers to do what this technique achieves, and in my view you really shouldn&#8217;t be using helpers for it in the [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[52,57,13],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-dj","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":282,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/282\/","url_meta":{"origin":825,"position":0},"title":"Class Helpers &#8211; Ruling from the Appellate Court","date":"01 Sep 2008","format":false,"excerpt":"My previous post on class helpers provoked a passionate response from some quarters who believed that they could be used \"safely\".\u00a0 More worrying was an apparent belief that their use was actually endorsed by CodeGear - tacitly or otherwise.\u00a0 A rather odd view given the advice from CodeGear themselves is\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":273,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/273\/","url_meta":{"origin":825,"position":1},"title":"Class Helpers On Trial","date":"30 Aug 2008","format":false,"excerpt":"Class helpers (introduced in Delphi 2007 2006 2005 - thanks to Chris and Bruce for the corrections) seem to be cropping up more and more frequently in suggested work-arounds or implementation approaches.\u00a0 I find this worrying given that this language feature has always come with the admonition from CodeGear that\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":683,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/683\/","url_meta":{"origin":825,"position":2},"title":"Class Helpers: Extending Classes for Context","date":"21 Nov 2010","format":false,"excerpt":"NEWSFLASH: I believe I have found a use for class helpers in the wild! This, even though I have long held the view that class helpers should not be viewed as a general purpose utility. They were designed for a very specific purpose and the authors of the technology themselves\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1207,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1207\/","url_meta":{"origin":825,"position":3},"title":"Adventures in Syntax: Something Old, Something New etc&#8230;","date":"20 Sep 2012","format":false,"excerpt":"As the post title says, this will be a brief detour through some features of the Pascal language and a presentation of some (theoretical) alternatives that could have been introduced instead. That is, some are real but little known syntax, others are what I think might be preferable to the\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":222,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/222\/","url_meta":{"origin":825,"position":4},"title":"More Deltics.Forms Magic","date":"24 Aug 2008","format":false,"excerpt":"Last time I introduced a bit of skullduggery with my Deltics.Forms unit as a way to easily \"inject\" a new TForm class into my projects.\u00a0 We used this new class to add public property that we could use to add a size grip control to any form. This time we\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1938,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1938\/","url_meta":{"origin":825,"position":5},"title":"Menu Items, APIs, Crackers and Hackers","date":"16 Oct 2013","format":false,"excerpt":"Francois Piette recently posted a solution to obtaining the screen position of a menu item involving using a \"hacker\" class. There is however a safer, more direct mechanism which I hope Francois won't mind me sharing and a far less safe related hacking technique that his post brought to mind.\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/825"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=825"}],"version-history":[{"count":6,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/825\/revisions"}],"predecessor-version":[{"id":830,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/825\/revisions\/830"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=825"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=825"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=825"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}