将TInterfacedObject转换为接口

dan*_*gph 5 delphi interface delphi-2007

根据Delphi文档,我可以TInterfacedObject使用as运算符转换为接口.

但它对我不起作用.强制转换产生编译错误:"运算符不适用于此操作数类型".

我正在使用Delphi 2007.

这是一些代码(控制台应用程序).标记包含错误的行.

program Project6;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  IMyInterface = interface
    procedure Foo;
  end;

  TMyInterfacedObject = class(TInterfacedObject, IMyInterface)
  public
    procedure Foo;
  end;

procedure TMyInterfacedObject.Foo;
begin
  ;
end;

var
  o: TInterfacedObject;
  i: IMyInterface;
begin
  try
    o := TMyInterfacedObject.Create;
    i := o as IMyInterface;  // <--- [DCC Error] Project6.dpr(30): E2015 Operator not applicable to this operand type
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.
Run Code Online (Sandbox Code Playgroud)

Cos*_*und 14

快速回答

您的界面需要具有GUID才能使as操作员工作.IMyInterface = interface在任何方法定义之前转到第一行,然后按Ctrl+ G以生成新的GUID.

更长的评论

as接口的运算符需要GUID,因为它调用IUnknown.QueryInterface,而这又需要GUID.如果在将INTERFACE转换为其他类型的INTERFACE时遇到此问题,那就没问题了.

你不应该投的TInterfacedObject在第一位置的接口,因为这意味着你同时持有A(参照实施对象TInterfacedObject),并已实现接口的引用(IMyInterface).这是有问题的,因为你混合了两个生命周期管理概念:TObject直到事情要求.Free它们为止; 你有理由确定.Free在你不知情的情况下没有任何东西要求你的物体.但接口引用计数:当你将你的界面给一个变量的引用计数器增加,当该实例用完的范围(或指定别的东西)的引用计数器减小.当参考计数器击中ZERO时,对象被丢弃(.Free)!

这里有一些无辜的代码会快速陷入困境:

procedure DoSomething(If: IMyInterface);
begin
end;

procedure Test;
var O: TMyObjectImplementingTheInterface;
begin
  O := TMyObjectImplementingTheInterface.Create;
  DoSomething(O); // Works, becuase TMyObject[...] is implementing the given interface
  O.Free; // Will likely AV because O has been disposed of when returning from `DoSomething`!
end;
Run Code Online (Sandbox Code Playgroud)

修复非常简单:将O类型更改TMyObject[...]IMyInterface,如下所示:

procedure DoSomething(If: IMyInterface);
begin
end;

procedure Test;
var O: IMyInterface;
begin
  O := TMyObjectImplementingTheInterface.Create;
  DoSomething(O); // Works, becuase TMyObject[...] is implementing the given interface
end; // `O` gets freed here, no need to do it manually, because `O` runs out of scope, decreases the ref count and hits zero.
Run Code Online (Sandbox Code Playgroud)