9

我需要一个没有引用计数的类实现接口。我做了以下事情:

  IMyInterface = interface(IInterface)
      ['{B84904DF-9E8A-46E0-98E4-498BF03C2819}'] 
      procedure InterfaceMethod;
  end;

  TMyClass = class(TObject, IMyInterface)
  protected
      function _AddRef: Integer;stdcall;
      function _Release: Integer;stdcall;
      function QueryInterface(const IID: TGUID; out Obj): HResult;stdcall;
  public
      procedure InterfaceMethod;
  end;

  procedure TMyClass.InterfaceMethod;
  begin
      ShowMessage('The Method');
  end;

  function TMyClass.QueryInterface(const IID: TGUID; out Obj): HResult;
  begin
      if GetInterface(IID, Obj) then
          Result := 0
      else
          Result := E_NOINTERFACE;
  end;

  function TMyClass._AddRef: Integer;
  begin
      Result := -1;
  end;

  function TMyClass._Release: Integer;
  begin
      Result := -1;
  end;

缺少引用计数可以正常工作。但我担心的是我不能TMyClass使用IMyInterfaceusingas运算符:

var
  MyI: IMyInterface; 
begin
  MyI := TMyClass.Create as IMyInterface;

我被给

[DCC 错误] E2015 运算符不适用于此操作数类型

TMyClass源自TInterfacedObject- 即我可以在没有编译器错误的情况下进行此类转换时,问题就会消失。显然我不想使用 TInterfacedObject 作为基类,因为它会使我的类引用计数。为什么不允许这种铸造以及如何解决它?

4

1 回答 1

15

您不能as在代码中使用的原因是您的类没有IInterface在其支持的接口列表中明确列出。即使您的接口派生自IInterface,除非您实际列出该接口,否则您的类不支持它。

所以,简单的解决方法是像这样声明你的类:

TMyClass = class(TObject, IInterface, IMyInterface)

您的类需要实现的原因IInterface是编译器依赖它来实现强制转换as

我想说的另一点是,一般来说,您应该避免使用接口继承。总的来说,它没有什么用处。使用接口的好处之一是您可以摆脱实现继承带来的单一继承约束。

但无论如何,所有 Delphi 接口都会自动继承,IInterface因此在您的情况下,没有必要指定它。我会这样声明你的界面:

IMyInterface = interface
  ['{B84904DF-9E8A-46E0-98E4-498BF03C2819}'] 
  procedure InterfaceMethod;
end;

更广泛地说,你应该尽量不要在你的接口中使用继承。通过采用这种方法,您将鼓励减少耦合并带来更大的灵活性。

于 2013-02-18T08:32:30.310 回答