{"id":500,"date":"2009-08-16T03:37:28","date_gmt":"2009-08-15T17:37:28","guid":{"rendered":"http:\/\/www.malcolmgroves.com\/blog\/?p=500"},"modified":"2015-03-13T11:05:31","modified_gmt":"2015-03-13T00:05:31","slug":"casting-an-interface-reference-to-the-implementing-class-in-delphi-2010","status":"publish","type":"post","link":"http:\/\/www.malcolmgroves.com\/blog\/?p=500","title":{"rendered":"Casting an Interface Reference to the Implementing Class in Delphi 2010"},"content":{"rendered":"<p>Not all the new features in Delphi 2010 are big. In fact, the team have spent a lot of time implementing many small features, fixes and tweaks. Some of these may not seem to amount to much individually, but they not only add up to significant impact, but greatly add to the polish of the product. I expect this will be one of those releases that keeps serving up little delights and surprises for a long time.<\/p>\n<p>One of the features in Delphi 2010 that I expect will spawn much debate is the ability to cast an interface reference back to the type of class that implements it.<\/p>\n<p><!--more-->Let\u2019s say we have an Interface, IMyInterface, and a class that implements that Interface, TMyClass:<\/p>\n<pre lang=\"Delphi\">  IMyInterface = interface\r\n  ['{7AD04980-5869-4C93-AC29-C26134511554}']\r\n    procedure Foo;\r\n  end;\r\n\r\n  TMyClass = class(TInterfacedObject, IMyInterface)\r\n    procedure Foo;\r\n    procedure Bar;\r\n  end;<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" style=\"margin: 10px 10px 10px 0px; display: inline; border-width: 0px;\" title=\"compileerror\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2009\/08\/compileerror.jpg\" alt=\"compileerror\" width=\"467\" height=\"254\" align=\"left\" border=\"0\" \/> Further, let\u2019s say we\u2019ve been passed a variable of type IMyInterface. What happens if we want to invoke Bar? Attempting to simply cast the interface reference to a TMyClass would result in a compiler error.<\/p>\n<p>The most common solution to this I\u2019ve seen is to have a method in the interface that returns the class type, but this kind of defeats much of the value of the interface in the first place, tying the interface to a specific implementation. Further, it\u2019s ugly as a hatful.<\/p>\n<p>Well, such hacks are no longer required.<\/p>\n<p>In Delphi 2010, you can now use the is operator to test to see if an interface type is implemented by a specific class, and if so, cast it to that type and reference any non-interface methods, properties, etc.<\/p>\n<p>Further, the as operator will throw an EInvalidCast exception if you attempt to cast an interface reference to a class type that it was not actually extracted from. The hard cast will return nil in the same circumstances. (Thanks Allen for the correction!)<\/p>\n<p>So this code now runs happily:<\/p>\n<pre lang=\"Delphi\">  if MyInterface is TMyClass then\r\n    TMyClass(MyInterface).Bar;<\/pre>\n<p>This needs to be used with some intelligence, of course. For example, the normal warnings about storing a reference-counted interface and a non-reference counted object reference to the same instance still apply.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Not all the new features in Delphi 2010 are big. In fact, the team have spent a lot of time implementing many small features, fixes and tweaks. Some of these may not seem to amount to much individually, but they not only add up to significant impact, but greatly add to the polish of the [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[19,48,51],"class_list":["post-500","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-delphi","tag-embarcadero","tag-interfaces"],"_links":{"self":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/500","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=500"}],"version-history":[{"count":9,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/500\/revisions"}],"predecessor-version":[{"id":1801,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/500\/revisions\/1801"}],"wp:attachment":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=500"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=500"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=500"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}