将对象作为接口传递

4

这应该是一个简单的答案,我相信它会是否定的,
但从一个较大的项目中,我有一个接口和过程。

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

我知道这个有效。

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

但是像这样做是否可能呢?
if supports(obj, iMyUnknown) then
  WorkObject(obj as iMyUnknown);
3个回答

5

为什么需要进行类型转换?

如果 obj 支持该接口,而你只需要在将其传递给过程之前检查一下,那么你可以直接传递该对象本身。编译器会处理其余的事情。只有当你想要访问接口的方法时,才需要在 Supports 调用中使用第三个参数。

编译并运行下面的代码。它应该能够无错误地编译,并呈现出控制台窗口和对话框消息。

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.

在我尝试的所有事情中,我简直不敢相信我没有尝试传递对象。谢谢。 - Christopher Chase

3
只要编译器知道您的对象支持IInterface,并且您的接口具有GUID,就可以使用as-cast将对象转换为接口。因此,它不能与TObject一起使用,但可以与TInterfacedObject一起使用。

难道不是反过来吗?而且难道没有IInterfaceComponentReference的解决方法吗? - Marco van de Voort

3

是的,你可以。自从该语言支持接口(大约在Delphi 3时)以来,as运算符就已经能够与接口一起使用了。您发布的代码有效,问题出在哪里?


1
当然,还有一个问题,为什么你想这样做。请注意,这意味着保留对接口和对象实例的引用,这可能会很棘手:当实例的引用计数降至0时,实例通常会被释放,此时您的实例引用将不再有效。更容易的方法是仅保留指向接口或实例的指针,而不是两者兼备。 - Ondrej Kelle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接