将子接口实现为其父接口参数的传递对象

我有一个父接口(IParent),一个子接口(IChild)和一个实现子接口的对象。

我试图通过传递实现子接口的对象数组来调用接受array of IParent参数的函数。

编译时出现以下错误:

[dcc32错误] Unit1.pas(46):E2010不兼容的类型:“ IParent”和 'TForm1'

unit Unit1;

interface

uses
  Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs;

type
  IParent = interface
    procedure DoSomething();
  end;

  IChild = interface(IParent)
    procedure DoSomethingElse();
  end;

  TForm1 = class(TForm,IChild)
    procedure FormCreate(Sender: TObject);
  public
    procedure DoSomething();
    procedure DoSomethingElse();
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure CallAllDoSomething(AArray : array of IParent);
var
  i : integer;
begin
  i := 0;
  while(i < Length(AArray)) do
  begin
    AArray[i].DoSomething();
    Inc(i);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Unit1.CallAllDoSomething([Self]);
end;

procedure TForm1.DoSomething();
begin
  ShowMessage('Something');
end;

procedure TForm1.DoSomethingElse();
begin
  ShowMessage('Something else');
end;

end.
zmg880831 回答:将子接口实现为其父接口参数的传递对象

您还必须在IParent的声明中添加TForm1

 TForm1 = class(TForm,IParent,IChild)
,

要直接将TForm1对象 分配给IParent,必须在IParent的声明中包含TForm1

TForm1 = class(TForm,IChild)

此行为记录在Embarcadero的DocWiki中:

Implementing Interface References

接口类型表达式不能引用其类实现后代接口的对象,除非该类(或从其继承的类)也显式实现祖先接口。

例如:

type
  IAncestor = interface
  end;
  IDescendant = interface(IAncestor)
    procedure P1;
  end;
  TSomething = class(TInterfacedObject,IDescendant)
    procedure P1;
    procedure P2;
  end;
     // ...
var
  D: IDescendant;
  A: IAncestor;
begin
  D := TSomething.Create;  // works!
  A := TSomething.Create;  // error
  D.P1;  // works!
  D.P2;  // error
end;

在此示例中,A被声明为IAncestor类型的变量。因为TSomething并未在实现的接口中列出IAncestor,所以无法将TSomething实例分配给A。但是,如果将TSomething的声明更改为:

TSomething = class(TInterfacedObject,IAncestor,IDescendant)
// ...

第一个错误将成为有效分配。 D被声明为IDescendant类型的变量。虽然D引用了TSomething的实例,但是您不能使用它来访问TSomething的P2方法,因为P2不是IDescendant的方法。但是,如果您将D的声明更改为:

D: TSomething;

第二个错误将成为有效的方法调用。

或者,由于IChild来自IParent,因此您可以明确地TForm1对象强制转换为IChild,然后让编译器为您将IChild转换为IParent

Unit1.CallAllDoSomething([IChild(Self)]);

此行为也得到记录:

Interface Assignment Compatibility

给定类类型的变量与该类实现的任何接口类型都分配兼容。接口类型的变量与任何祖先接口类型都兼容分配。值nil可以分配给任何接口类型的变量。

本文链接:https://www.f2er.com/2428387.html

大家都在问