views:

163

answers:

3

This should be a simple answer, i believe its going to be a no,
but taken from a larger project, i have an interface and the procedure

iMyUnknown= interface(IInterface)
 ['..GUID..']
end;
procedure WorkObject(iObj :iMyUnknown);

i know this works

var 
  MyUnknown : iMyUnknown;
begin
 if supports(obj, iMyUnknown, MyUnknown) then
  WorkObject(MyUnknown);

But is it possible to do something like this?

if supports(obj, iMyUnknown) then
  WorkObject(obj as iMyUnknown);
+3  A: 

You can cast an object to an interface with an as-cast, as long as the compiler knows that your object supports IInterface, and your interface has a GUID. So it won't work with TObject, but with TInterfacedObject it will.

Mason Wheeler
Isn't it the other way around? And isn't there a IInterfaceComponentReference workaround for that?
Marco van de Voort
+3  A: 

Why would you need to cast?

If obj supports the interface, and all you need to do is check that before passing it to a procedure, you can simply pass the object itself. The compiler will take care of the rest. You only need the third param on the Supports call if you want to access methods of the interface.

Compile and run the code below. It should compile without errors and present you with a console window and a dialog message.

program Project1;

{$APPTYPE CONSOLE}

uses
  Classes
  , Dialogs
  , SysUtils
  ;

type
  iMyUnknown = interface(IInterface)
  ['{DA867EBA-8213-4A91-8E03-1AACA150CE77}']
    procedure DoSomething;
  end;

  TMuster = class(TInterfacedObject, iMyUnknown)
    procedure DoSomething;
  end;

procedure WorkObject(iObj: iMyUnknown);
begin
  if Assigned(iObj) then ShowMessage('Got something');
end;

{ TMuster }

procedure TMuster.DoSomething;
begin
  beep;
end;

var
  obj: TMuster;
begin
  try
    obj := TMuster.Create;
    if Supports(obj, iMyUnknown) then
      WorkObject(obj);
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.
Marjan Venema
thankyou. Out of all the things i tried, i cant believe i didn't just try passing the object.
Christopher Chase
:) we've all been there...
Marjan Venema
+3  A: 

Yes, you can. The as operator worked with interfaces ever since the support for interfaces has been added to the language (around Delphi 3, IIRC). The code you posted works. Where is the problem?

TOndrej
Of course, there's also a question, why would you want to do that. Be aware that it implies keeping a reference to both the interface and the object instance which may be tricky: the instance will normally be freed when its reference count drops to 0 at which point your instance reference is no longer valid. It's easier to keep only pointers to interfaces, or pointers to instances, not both.
TOndrej