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

Delphi 传递将子接口实现为其父接口参数的对象,delphi,interface,delphi-xe7,Delphi,Interface,Delphi Xe7,我有一个父接口IParent、一个子接口IChild和一个实现子接口的对象 我试图调用一个函数,该函数通过传递实现子接口的对象数组来接受IParent参数数组 编译时出现以下错误: [dcc32错误]Unit1.pas46:E2010不兼容类型:“iPart”和 “TForm1” 您还必须将IParent添加到TForm1的声明中: 您还必须将IParent添加到TForm1的声明中: 要将TForm1对象直接指定给iPart,必须在TForm1的声明中包含iPart: TForm1=类TFor

我有一个父接口IParent、一个子接口IChild和一个实现子接口的对象

我试图调用一个函数,该函数通过传递实现子接口的对象数组来接受IParent参数数组

编译时出现以下错误:

[dcc32错误]Unit1.pas46:E2010不兼容类型:“iPart”和 “TForm1”

您还必须将IParent添加到TForm1的声明中:

您还必须将IParent添加到TForm1的声明中:

要将TForm1对象直接指定给iPart,必须在TForm1的声明中包含iPart:

TForm1=类TForm,iPart,IChild 此行为记录在Embarcadero的DocWiki中:

接口类型表达式不能引用其类实现子接口的对象,除非该类或其继承的类也显式实现了祖先接口

例如:

类型 IAncestor=接口 终止 idescenedant=interface 程序P1; 终止 TSomething=classTInterfacedObject,IdeScentant 程序P1; 程序P2; 终止 // ... 变量 D:创意设计师; A:安内斯托; 开始 D:=TSomething.Create;//作品 A:=TSomething.Create;//错误 D.P1;//作品 D.P2;//错误 终止 在本例中,A被声明为IAncestor类型的变量。由于TSomething未在其实现的接口中列出IAncestor,因此不能将TSomething实例分配给。但是,如果您将TSomething的声明更改为:

TSomething=classTInterfacedObject、Ianstor、IdeScentant // ... 第一个错误将成为有效的赋值。D被声明为IDescendant类型的变量。虽然D引用了TSomething的实例,但您不能使用它访问TSomething的P2方法,因为P2不是IdeScentant的方法。但是如果你把D的声明改成:

D:某物; 第二个错误将成为有效的方法调用

或者,由于IChild源自iPart,因此可以先将TForm1对象显式强制转换为IChild,然后让编译器将IChild转换为iPart:

单元1.称之为一切事物[IChildSelf]; 这种行为也被记录在案:

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

要将TForm1对象直接指定给iPart,必须在TForm1的声明中包含iPart:

TForm1=类TForm,iPart,IChild 此行为记录在Embarcadero的DocWiki中:

接口类型表达式不能引用其类实现子接口的对象,除非该类或其继承的类也显式实现了祖先接口

例如:

类型 IAncestor=接口 终止 idescenedant=interface 程序P1; 终止 TSomething=classTInterfacedObject,IdeScentant 程序P1; 程序P2; 终止 // ... 变量 D:创意设计师; A:安内斯托; 开始 D:=TSomething.Create;//作品 A:=TSomething.Create;//错误 D.P1;//作品 D.P2;//错误 终止 在本例中,A被声明为IAncestor类型的变量。由于TSomething未在其实现的接口中列出IAncestor,因此不能将TSomething实例分配给。但是,如果您将TSomething的声明更改为:

TSomething=classTInterfacedObject、Ianstor、IdeScentant // ... 第一个错误将成为有效的赋值。D被声明为IDescendant类型的变量。虽然D引用了TSomething的实例,但您不能使用它访问TSomething的P2方法,因为P2不是IdeScentant的方法。但是如果你把D的声明改成:

D:某物; 第二个错误将成为有效的方法调用

或者,由于IChild源自iPart,因此可以先将TForm1对象显式强制转换为IChild,然后让编译器将IChild转换为iPart:

单元1.称之为一切事物[IChildSelf]; 这种行为也被记录在案:

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


的确如果没有IParent的列表,TForm1.DoSomething实际上是IChild.DoSomething的实现,而不是IParent.DoSomething。如果没有iPart的列表,TForm1.DoSomething实际上是IChild.DoSomething的实现,而不是iPart.Dosomethi ng。
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.
 TForm1 = class(TForm, IParent, IChild)