// you’re reading...

Development

Casting an Interface Reference to the Implementing Class in Delphi 2010

Image ©2007-2009 ~FractalAngel-Stock 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.

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.

Let’s say we have an Interface, IMyInterface, and a class that implements that Interface, TMyClass:

  IMyInterface = interface
  ['{7AD04980-5869-4C93-AC29-C26134511554}']
    procedure Foo;
  end;
 
  TMyClass = class(TInterfacedObject, IMyInterface)
    procedure Foo;
    procedure Bar;
  end;

compileerror Further, let’s say we’ve 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.

The most common solution to this I’ve 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’s ugly as a hatful.

Well, such hacks are no longer required.

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.

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!)

So this code now runs happily:

  if MyInterface is TMyClass then
    TMyClass(MyInterface).Bar;

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.

Related Posts

    Generic Interfaces in Delphi
    In the Development category
    By Malcolm
    A TDictionary explanation
    In the Development category
    By Malcolm
    Storing code in a collection : TDictionary and Anonymous Methods
    Storing code in a collection : TDictionary and Anonymous Methods
    In the Development category
    By Malcolm
    IOUtils.pas – OO File System Access in Delphi 2010
    IOUtils.pas – OO File System Access in Delphi 2010
    In the Development category
    By Malcolm
    More Attributes in Delphi 2010
    More Attributes in Delphi 2010
    In the Development category
    By Malcolm

Discussion

16 comments for “Casting an Interface Reference to the Implementing Class in Delphi 2010”

  1. Cool. Small detail, you might want to update the image, you are calling Foo instead of Bar.

    Posted by J.D. Mullin | August 19, 2009, 4:22 am
  2. Actually the “as” cast will still raise an EInvalidCast exception if the interface isn’t implemented by the specific object type. The hard-cast will return nil if the interface is not implemented by the casting object.

    Allen.

    Posted by Allen Bauer | August 19, 2009, 6:09 am
  3. Awesome, I make use of non refcounted (AddRef etc overridden) interfaced objects to share with C++ and avoid troublesome circular references in complex situations. I generally have a GetObject method in each interface to get to the implementing class, just perfect!

    It would be cool if I could disable the automatic refcounting for these sepecific non-refcounted objects altogether as well.

    Thanks for sharing Malcolm, keep the “small” stuff coming!

    Posted by Bas | August 19, 2009, 7:26 am
  4. Twitter Comment


    Casting an Interface Reference to the Implementing Class in Delphi 2010 [link to post]

    - Posted using Chat Catcher

    Posted by embt_asia (Embarcadero Asia) | August 20, 2009, 7:51 am
  5. This is really cool! I’ve seen people implement this through horrible hacks, and so I think you’re right, it’ll be very nice to have this as a supported feature.

    Will this work in C++?

    Posted by David M | August 20, 2009, 10:58 am
  6. [...] Malcolm Groves shows off YACLF* in Delphi 2010. [...]

    Posted by Nick Hodges » Blog Archive » Random Thoughts on the Passing Scene #120 | August 20, 2009, 11:55 am
  7. Now THAT is gonna save a few seconds, but more importantly clean up a bit of code.

    You don’t say if any caution has to be exercised when working with interface references to implementing code that is not a Delphi class in the same process.

    Does this simply yield a NIL or do you have to exercise caution when (potentially) applying this method to such interface references?

    Posted by Jolyon Smith | August 20, 2009, 12:48 pm
  8. very good!!! using inteface like this is more readable and intutive. Good work, tnkx

    Posted by Ivan Revelli | August 20, 2009, 6:45 pm
  9. J.D. : Ahh, good catch. Thanks.

    Allen : Thanks for that, I’ll update the post.

    Posted by Malcolm | August 20, 2009, 7:33 pm
  10. I attended one of Danny’s “Reading Tea Leaves: The Fine Art of Debugging” sessions at BorCon several years back, so I know that this isn’t so trivial. I’d love to hear some gritty details about how this was implemented, and how you make it work even though the interface in question might be COM and not follow Delphi conventions.

    Posted by Joe White | August 21, 2009, 12:41 am
  11. Hi Jolyon,

    I’ll have to check, but I think it only works if the class that implements the interface is a Delphi class. I’ll check it out though.

    Cheers
    Malcolm

    Posted by Malcolm | August 21, 2009, 10:25 am
  12. [...] that in mind, I thought it very much a Good Thing when Malcolm Groves reported how yet another COM-related quirk — namely, the inability to cast from an interface to an [...]

    Posted by Querying for the implementing object from an interface (1 « Delphi Haven) | August 22, 2009, 10:09 pm
  13. [...] mentioned earlier that a lot of work in this release had gone into smaller features and feature tweaks. One [...]

    Posted by Malcolm Groves | Refactoring Support for Attributes in Delphi 2010 | August 27, 2009, 5:52 pm
  14. Would it be possible to have a way of getting an interface name from a GUID ?

    If the interface above is served up by a factory, done by something like Factory.GetObject(IMyInterface)

    and lets say that for some reason the object that implements this class hasn’t been registered, then when debugging, the developer gets a message something like

    ‘Could not find object for 7AD04980-5869-4C93-AC29-C26134511554′

    … Which isn’t particularly useful.

    It would be nice if the compiler could somehow match the interface name with the GUID.

    I have written a small script that generates a list of GUID, Interface name combinations, but it’s a bit nasty because the file can get out of date if the script is not rerun after a change.

    …Would be nice to have better interface ‘metadata’ support.

    Cheers
    DC

    Posted by DC | December 16, 2009, 12:35 pm
  15. Knew I’d seen this mentioned somewhere before. I’m about to use it to invade the internals of my interface instances so I can unit test them.

    Thanks for posting this originally, I think I would have missed it otherwise.

    Posted by Lachlan Gemmell | January 16, 2010, 11:26 am
  16. [...] Groves, no parece casual ya que anteriormente, podemos encontrar en su blog, y concretamente en Casting an Interface Reference to the Implementing Class in Delphi 2010 de fecha 16 deAgosto de 2009, una referencia a una de las novedades introducidas en Delphi 2010, [...]

    Posted by Delphi básico: Lo más básico de Delphi | March 29, 2010, 10:20 am

Post a comment

Subscribe to RSS Follow on Twitter Connect on LinkedIn Connect on Facebook Subscribe on YouTube Subscribe on iTunes

Recent Tweets

This is a personal website. As such, any opinions expressed are my own, and do not necessarily represent the views of my employer, Embarcadero Technologies.