{"id":87,"date":"2012-10-25T19:57:01","date_gmt":"2012-10-25T17:57:01","guid":{"rendered":"http:\/\/blog.kassebaum.eu\/?p=87"},"modified":"2012-10-25T19:57:01","modified_gmt":"2012-10-25T17:57:01","slug":"objguard","status":"publish","type":"post","link":"https:\/\/www.kassebaum.eu\/blog\/2012\/10\/25\/objguard\/","title":{"rendered":"ObjGuard"},"content":{"rendered":"<p>Sometimes it happens that I would like to convert a Delphi object to an interfaces. Interfaces offer some advantages.<br \/>\nOn the one hand you can handle different objects that are not derived from a common hierarchy but share the same methods.<br \/>\nOn the other hand interfaces are reference counted. You can use the reference counting as a poor man&#8217;s garbage collection.<\/p>\n<p>Normally objects that are interfaced are derived from TInterfacedObject.<br \/>\nLet&#8217;s have a look at the implementation of TInterfacedObject in Delphi XE3.<\/p>\n<pre class=\"lang:delphi decode:true\" title=\"TInterfacedObject\">...\r\n  TInterfacedObject = class(TObject, IInterface)\r\n  protected\r\n{$IFNDEF AUTOREFCOUNT}\r\n    FRefCount: Integer;\r\n{$ENDIF}\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...\r\n\r\nfunction TInterfacedObject._AddRef: Integer;\r\nbegin\r\n{$IFNDEF AUTOREFCOUNT}\r\n  Result := AtomicIncrement(FRefCount);\r\n{$ELSE}\r\n  Result := __ObjAddRef;\r\n{$ENDIF}\r\nend;\r\n\r\nfunction TInterfacedObject._Release: Integer;\r\nbegin\r\n{$IFNDEF AUTOREFCOUNT}\r\n  Result := AtomicDecrement(FRefCount);\r\n  if Result = 0 then\r\n    Destroy;\r\n{$ELSE}\r\n  Result := __ObjRelease;\r\n{$ENDIF}\r\nend;\r\n...<\/pre>\n<p>You can see two things:<\/p>\n<ol>\n<li>Every interfaced object has to implement IInterface.<\/li>\n<li>EMBT will introduce a real garbage collection but currently a TInterfacedObject is simply reference counted.<\/li>\n<\/ol>\n<p>Normally you have to decide whether an object is interfaced or not if you are <strong>implementing<\/strong> it, not if you are<strong> using<\/strong> it.<br \/>\nThat&#8217;s why I introduced a small wrapper class for an object. The wrapper class is interfaced and offers full access to the underlying object.<\/p>\n<pre class=\"lang:delphi decode:true \" title=\"ObjGuard\" >unit ObjGuard;\r\n\r\ninterface\r\n\r\ntype\r\n  IObjGuard&lt;T: class&gt; = interface(IInterface)\r\n  ['{7FBC48DC-1ED4-450F-8418-64E0D942F115}']\r\n    function get_Obj: T;\r\n    property Obj: T read get_Obj;\r\n  end;\r\n\r\n  TObjGuard&lt;T: class&gt; = class(TInterfacedObject, IObjGuard&lt;T&gt;)\r\n  strict private\r\n    FObj: T;\r\n    function get_Obj: T; inline;\r\n  strict protected\r\n    property Obj: T read get_Obj;\r\n  public\r\n    constructor Create(AObj: T);\r\n    destructor Destroy; override;\r\n  end;\r\n\r\nimplementation\r\n\r\nuses\r\n  System.Classes;\r\n\r\n{ TObjGuard&lt;T&gt; }\r\n\r\nconstructor TObjGuard&lt;T&gt;.Create(AObj: T);\r\nbegin\r\n  inherited Create;\r\n  FObj := AObj;\r\nend;\r\n\r\ndestructor TObjGuard&lt;T&gt;.Destroy;\r\nbegin\r\n  FObj.Free;\r\n  inherited Destroy;\r\nend;\r\n\r\nfunction TObjGuard&lt;T&gt;.get_Obj: T;\r\nbegin\r\n  Result := FObj;\r\nend;\r\n\r\nend.<\/pre>\n<p>This makes the use of the object very simple. Just create an instance of the ObjGuard and the resulting interface offers access to the underlying object.<br \/>\nYou can use it for example in records which don&#8217;t offer a destructor so that there must be a way to destroy object fields.<\/p>\n<pre class=\"lang:delphi decode:true \" title=\"Use of TObjGuard\" >...\r\ntype\r\n  TMyRecord = record\r\n  strict private\r\n    FStream: IObjGuard&lt;TFileStream&gt;;\r\n    function get_Stream: TStream; inline;\r\n  public\r\n    constructor Create(const AFileName: string);\r\n    property Stream: TFileStream read get_Stream;\r\n  end;\r\n\r\n...\r\nconstructor TMyRecord.Create(const AFileName: string);\r\nbegin\r\n  FStream := TObjGuard&lt;TFileStream&gt;.Create(TFileStream.Create(AFileName, fmCreate));\r\nend;\r\n\r\nfunction TMyRecord.get_Stream: TStream;\r\nbegin\r\n  Result := FStream.Obj;\r\nend;\r\n\r\nend.<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes it happens that I would like to convert a Delphi object to an interfaces. Interfaces offer some advantages. On the one hand you can handle different objects that are not derived from a common hierarchy but share the same &hellip; <a href=\"https:\/\/www.kassebaum.eu\/blog\/2012\/10\/25\/objguard\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[5],"class_list":["post-87","post","type-post","status-publish","format-standard","hentry","category-tipsandtricks","tag-delphi"],"_links":{"self":[{"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/posts\/87","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/comments?post=87"}],"version-history":[{"count":8,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/posts\/87\/revisions"}],"predecessor-version":[{"id":95,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/posts\/87\/revisions\/95"}],"wp:attachment":[{"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/media?parent=87"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/categories?post=87"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/tags?post=87"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}