{"id":644,"date":"2010-07-29T09:56:52","date_gmt":"2010-07-28T21:56:52","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=644"},"modified":"2010-07-30T09:13:11","modified_gmt":"2010-07-29T21:13:11","slug":"when-is-an-interfaced-object-not-an-interfaced-object","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/644\/","title":{"rendered":"When is an interfaced object not an interfaced object?"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">5<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p><strong>Answer<\/strong>: <em>When it is merely the container for an interface.<\/em><\/p>\n<p>After a long series of observation and opinion pieces, I thought it about time I posted something a little more  technical, so here we go.<br \/>\n<!--more--><br \/>\nI think it is a well known practice to store references to objects in the <strong>Tag<\/strong>, <strong>Data<\/strong> or <strong>Objects<\/strong> members of various VCL classes and controls. \u00a0This is often used for example with <strong>TListBox<\/strong>, <strong>TComboBox<\/strong>, <strong>TListView<\/strong> and <strong>TTreeView<\/strong> &#8211; among many others &#8211; to hold a reference to an object that an item in one of those controls refers to:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\nvar\r\n\u00a0\u00a0cust: TCustomer;\r\nbegin\r\n\u00a0\u00a0\/\/ do something to acquire a cust reference...\r\n   :\r\n  \/\/ ...and add it to a listbox:\r\n\r\n\u00a0\u00a0lbCustomers.Items.AddObject(cust.Name, cust);\r\nend;\r\n<\/pre>\n<p>The object can then be later retrieved by simply casting the corresponding entry in the listbox <strong>Objects<\/strong> property:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\nvar\r\n  selectedCust: TCustomer;\r\nbegin\r\n  \/\/ Get the selected customer:\r\n\r\n  selectedCust := TCustomer(lbCustomers.Items.Objects[lbCustomers.ItemIndex]);\r\nend;\r\n<\/pre>\n<p>or<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  selectedCust := lbCustomers.Items.Objects[lbCustomers.ItemIndex] as TCustomer;\r\n<\/pre>\n<p>Incidentally, this is an example of one of the few (very few) cases where I consider <strong>with<\/strong> to be very helpful, entirely safe and unlikely to fall foul of the debugger shortcomings (i.e. unlikely to require debugging and\/or the debugger shortcomings easily circumvented since there is an explicit symbol &#8211; <strong>lbCustomers<\/strong> &#8211; that can be used to evaluate any values explicitly that the debugger is unable to resolve implicitly itself.  I wish the people who spend so much time arguing against the use of with would put as much energy into asking for the debugger to be fixed &#8211; the compiler and the IDE have no trouble with this construct, the debugger shouldn&#8217;t either):<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  with lbCustomers do\r\n    selectedCust := TCustomer(Items.Objects[ItemIndex]);\r\n<\/pre>\n<p>or<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  with lbCustomers do\r\n    selectedCust := Items.Objects[ItemIndex] as TCustomer;\r\n<\/pre>\n<p>But I digress.<\/p>\n<p>The question relevant to this post is:  What if the object reference you wish to store in one of the properties (<strong>Tag<\/strong>, <strong>Data<\/strong>, <strong>Objects<\/strong> etc) isn&#8217;t an <em>object reference<\/em> but is instead an <em>interface reference<\/em>?<\/p>\n<p>Casting an interface reference into a suitable form for storage in a non-interface typed property is both messy and risky.  An alternative technique is to &#8220;wrap&#8221; the interface inside an object:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  type\r\n    TInterface = class\r\n    \/\/ A naive implementation of an interface wrapper\r\n    private\r\n      fRef: IUnknown;\r\n    public\r\n      constructor Create(const aRef: IUnknown);\r\n      property Ref: IUnknown read fRef;\r\n    end;\r\n\r\n\r\n  constructor TInterface.Create(const aRef: IUnknown);\r\n  begin\r\n    inherited Create;\r\n    fRef := aRef;\r\n  end;\r\n<\/pre>\n<p><em><strong>NOTE:<\/strong> By design this class is intended to capture and maintain a reference to an interface, so the reference itself is read-only, but making it writable is a (seemingly) trivial change, if required.<\/em><\/p>\n<p>This preserves the interface reference count by maintaining the interface reference but provides a much more simply managed object reference that can be used in all those places that an <strong>Integer<\/strong>, <strong>Pointer<\/strong> or <strong>TObject<\/strong> storage &#8220;slot&#8221; is provided.<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\nvar\r\n\u00a0\u00a0cust: ICustomer;\r\nbegin\r\n\u00a0\u00a0\/\/ do something to acquire a cust reference...\r\n   :\r\n  \/\/ ...and add it to a listbox:\r\n\r\n\u00a0\u00a0lbCustomers.Items.AddObject(cust.Name,\r\n                              TInterface.Create(ICustomer));\r\nend;\r\n<\/pre>\n<p>One thing to be aware of here is that when subsequently removing or clearing items from a listbox (or clearing <strong>Tag<\/strong>, <strong>Data<\/strong> or other properties used to hold a <strong>TInterface<\/strong> reference) the current contents of course now need to be <strong>Free<\/strong>&#8216;d.<\/p>\n<p>Retrieving our stored interface is relatively straightforward:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\nvar\r\n  intf: TInterface;\r\n  selectedCust: ICustomer;\r\nbegin\r\n  \/\/ Get the selected customer:\r\n\r\n  with lbCustomers do\r\n    intf := TInterface(Items.Objects[ItemIndex]);\r\n\r\n  selectedCust := intf.Ref as ICustomer;\r\nend;\r\n<\/pre>\n<p>The requirement to include the use of the <strong>Ref<\/strong> member is more cumbersome than it needs to be however, and beings me to the original question posed in the title of this post.  We also need to address the naivety of the implementation (you did spot that in the comment of the original code above, right?).<\/p>\n<p>So first, how to eliminate the need to use the <strong>Ref<\/strong> property (indeed, to eliminate the property entirely).<\/p>\n<p>I realised I could do this by implementing my wrapper class itself as an interfaced object but eliminating the reference counted lifetime semantics and indeed delegating ALL interface related behaviour to the captured interface itself.<\/p>\n<p>We can do this in Delphi because the implementation of IUnknown (the basis for all interface behaviour in Delphi) is not hidden in some inaccessible part of the runtime, but is explicit in the implementation in our own code.  It only appears automatic and &#8220;magic&#8221; because we most often <em>inherit<\/em> this behaviour from a suitable base class.<\/p>\n<p>The only difference here is that the implementation will be provided (and customised) on a class derived directly from <strong>TObject<\/strong> with no existing <strong>IUnknown<\/strong> support of its own:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n    TInterface = class(TObject, IUnknown)\r\n    private\r\n      fRef: IUnknown;\r\n    protected\r\n      \/\/ IUnknown\r\n      function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;\r\n      function _AddRef: Integer; stdcall;\r\n      function _Release: Integer; stdcall;\r\n    public\r\n      constructor Create(const aRef: IUnknown);\r\n    end;\r\n\r\n\r\n  constructor TInterface.Create(const aRef: IUnknown);\r\n  begin\r\n    inherited Create;\r\n    fRef := aRef;\r\n  end;\r\n\r\n  function TInterface.QueryInterface(const IID: TGUID; out Obj): HResult;\r\n  begin\r\n    result := fRef.QueryInterface(IID, Obj);\r\n  end;\r\n\r\n  function TInterface._AddRef: Integer;\r\n  begin\r\n    result := 1;\r\n  end;\r\n\r\n  function TInterface._Release: Integer;\r\n  begin\r\n    result := 1;\r\n  end;\r\n<\/pre>\n<p>With this implementation of <strong>IUnknown<\/strong> in place, the wrapper class will not have a reference counted lifetime and any interface queries made of it are delegated to the captured interface.  When retrieving the captured interface we can now do so directly:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\nvar\r\n  intf: TInterface;\r\n  selectedCust: ICustomer;\r\nbegin\r\n  \/\/ Get the selected customer:\r\n\r\n  with lbCustomers do\r\n    intf := TInterface(Items.Objects[ItemIndex]);\r\n\r\n  selectedCust := intf as ICustomer;\r\nend;\r\n<\/pre>\n<p>Which leaves only the naivety in the implementation to be address.<\/p>\n<p>The naivety is that the wrapper is holding the reference as an <strong>IUnknown<\/strong> but is doing so by using the fact that all interfaces ultimately extend <strong>IUnknown<\/strong> and are consequently assignment compatible.  The wrapper is not actually obtaining the <em>true<\/em> <strong>IUnknown<\/strong> implementation of the interface.<\/p>\n<p>As it stands, this isn&#8217;t actually an issue for the class, as implemented.  This naivety only really becomes a problem when comparing interface references for equality:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  var\r\n     a, b: IUnknown;\r\n     c: ICustomer;\r\n  begin\r\n     \/\/ Assuming a valid customer reference in c...\r\n\r\n     a := c;\r\n     b := c as IUnknown;\r\n     \r\n     \/\/ a &lt;&gt; b !!\r\n  end;\r\n<\/pre>\n<p>To be sure of comparing interfaces in this way you have to reduce them to a true, common denominator &#8211; e.g. a genuine <strong>IUnknown<\/strong> reference.<\/p>\n<p>This requires a simple modification to our constructor and then simplifies the provision of a handy additional function on our wrapper class &#8211; an equality test:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  constructor TInterface.Create(const aRef: IUnknown);\r\n  begin\r\n    inherited Create;\r\n    fRef := aRef as IUnknown;\r\n  end;\r\n\r\n  function TInterface.IsEqual(const aOther: IUnknown): Boolean;\r\n  begin\r\n    result := ((aOther as IUnknown) = fRef);\r\n  end;\r\n<\/pre>\n<p>So, for example, to select a specific customer in a populated listbox:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\nprocedure SelectCustInListbox(const aCustomer: ICustomer; const aListbox: TListbox);\r\nvar\r\n  i, selIdx: Integer;\r\nbegin\r\n  \/\/ Assuming some cust ref to be selected in the list\r\n  \r\n  selIdx := -1;\r\n  for i := 0 to Pred(aListBox.Count) do\r\n  begin\r\n    if TInterface(aListBox.Objects[i]).IsEqual(aCustomer) then\r\n    begin\r\n      selIdx := i;\r\n      BREAK;\r\n    end;\r\n  end;\r\n\r\n  aListbox.ItemIndex := selIdx;\r\nend;\r\n<\/pre>\n<p>Now of course, it should be readily apparent that such a routine need not be specific to an <strong>ICustomer<\/strong> type reference and could be used to select <em>any<\/em> interface reference in a list box with interface references captured by <strong>TInterface<\/strong> objects.<\/p>\n<p><em><strong>FINAL NOTE:<\/strong> I said that converting the <strong>Ref<\/strong> property to a writable value was a &#8220;seemingly&#8221; trivial change.  It is, but if you choose to retain the <strong>Ref<\/strong> property in order to make it writable (there is no other purpose for it now that our wrapper exposes the interface more directly) then you should ensure that you use a setter method and convert the interface to <strong>IUnknown<\/strong> when updating the captured interface reference into the <strong>fRef<\/strong> member.  Alternatively you could modify the implementation of <strong>IsEqual()<\/strong> to convert both interfaces to <strong>IUnknown<\/strong> at the time of comparison<\/em><\/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\">5<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> Answer: When it is merely the container for an interface. After a long series of observation and opinion pieces, I thought it about time I posted something a little more technical, so here we go.<\/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":[292,109,29,110],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-ao","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":391,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/391\/","url_meta":{"origin":644,"position":0},"title":"Free Yourself","date":"27 Sep 2008","format":false,"excerpt":"Barry Kelly recently posted an example of \"smart\" pointers (specifically the auto-pointer variant of a smart pointer) using generics in Delphi 2009.\u00a0 It was an interesting use of generics but the end result was something that has - in part at least - been possible for some time in Delphi\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1930,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1930\/","url_meta":{"origin":644,"position":1},"title":"VCL Threading &#8211; Indeterminate Lifetimes","date":"18 Oct 2013","format":false,"excerpt":"Sometimes when you launch a thread you don't know when it will complete whatever processing it is tasked with. Sometimes you do. Sometimes it may never complete and will require that you expressly terminate it. Usually any given thread will have a lifecycle that is at least consistently one or\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":876,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/876\/","url_meta":{"origin":644,"position":2},"title":"Commonest Weakness&#8230;","date":"06 Jun 2012","format":false,"excerpt":"Stefan Glienke recently added his contribution to the various solutions for implementing weak interface references in Delphi. He quite neatly and comprehensively covers the need for such things, but his approach requires generics support and so is limited to later versions of the compiler (just how late really depends on\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1624,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1624\/","url_meta":{"origin":644,"position":3},"title":"Exploring Listeners With Oxygene","date":"16 Sep 2013","format":false,"excerpt":"Part 2 in a short series demonstrating the development of a simple camera app for Android using Oxygene. In the previous instalment we looked at the basic framework of our app. For this instalment I was going to show how to implement the camera preview or viewfinder for this instalment,\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":961,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/961\/","url_meta":{"origin":644,"position":4},"title":"Thinking Creatively with QueryInterface()","date":"02 Aug 2012","format":false,"excerpt":"I soon hope to be releasing \"Smoketest\", a testing framework that I have developed over the past few years. It has actually been in production use for most of that time (albeit by my own good self) but also continues to develop and evolve. \u00a0On the occasions when I have\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":412,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/412\/","url_meta":{"origin":644,"position":5},"title":"Proposal for Automated Variables","date":"01 Oct 2008","format":false,"excerpt":"Or: \"Environmentally Friendly Coding - Recycle Your Keywords\" Yesterday I logged a Quality Central report proposing the addition of support for \"automatic variables\" to the Delphi language.\u00a0 Not only is it an excellent idea (in my humble and utterly objective opinion :)), but there is already a keyword in the\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\/644"}],"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=644"}],"version-history":[{"count":8,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/644\/revisions"}],"predecessor-version":[{"id":651,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/644\/revisions\/651"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=644"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=644"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=644"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}