调用从接口和另一个祖先继承的类的方法

saa*_*stn 5 delphi oop interface multiple-inheritance

我在实现某些类之间的关系时遇到问题.我有三个不同的课程,提供三种不同的形式.所有这些类都使用相同的语言,因此它们是从同一个类中继承的TAncestorServer.让我们把它的后代TForm1Server,TForm2ServerTForm3Server.TAncestorServer包含一个名为的抽象方法Function1,所以TForm1,TForm2并且TForm3可以通过它们自己继承的类来调用它,它们可以通过名为的属性访问类Server.但问题在于另一种形式叫做TForm4!它与其他形式非常相似,但它并不像他们那样独立.它适用于TForm2ServerTForm3Server.还没问题,但像想象另一种方法,Function2这是在宣布TForm2ServerTForm3Server,TForm4需要给他们打电话.我可以这样:

if Server is TForm2Server then
   TForm2Server(Server).Function2
else if Server is TForm3Server then
  TForm3Server(Server).Function2;
Run Code Online (Sandbox Code Playgroud)

但它可以变成一个无限的if-else子句!所以我认为像多重继承这样的东西可能会有所帮助.我声明了一个名为IForm4Servercontains 的接口Function2.所以TForm2Server,TForm3Server继承两者TAncestorServerIForm4Server.我认为这样的事情可行:

If Server is IForm4Server then
  IForm4Server(Server).Function2;
Run Code Online (Sandbox Code Playgroud)

但是编译器不这么认为,它说它不是一个有效的类型转换,因为TAncestorServer它不是IForm4Server,这是绝对正确的.TForm1Server不知道实施Function2,不得不留空.我不能宣布TForm4.ServerIForm4Server过,因为Function1代表的方法和属性数量庞大,但是我还是不能强制类型转换IForm4ServerTAncestorServer.

作为一个解决方案,我可以定义两个不同的性质TForm4类似GeneralServer: TAncestorServer,并Form4Server: IForm4Server然后分配的同一个实例TForm2ServerTForm3Server给他们,但我并不感觉良好.我该怎么做?它有什么标准模式吗?

jac*_*ate 6

实现一个或多个接口是正确的方法,但看起来你对正确的语法有点困惑,并且没有接口经验.

基本的东西是:

  • 对于任意数量的类,您都有一个共同的祖先类(或表单).祖先声明了类以某种方式专门化的虚方法.
  • 使用任意数量的方法声明接口.不要忘记在界面中添加GUID.
  • 扩展表单声明以实现声明的接口,将接口添加到类声明并添加声明的方法.
  • 你现在可以:
    • 使用祖先类多态调用任何虚方法
    • 询问任何形式是否实现了接口,如果是,请检索对它的接口引用并调用任何接口方法.所有这些都可以使用支持功能完成.

我做了一个我能想到的最简单的例子,使用视觉继承表单和简单的界面.该示例的摘录如下:

共同的祖先类:

type
  TServerForm = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
    procedure Method1; virtual;
  end;
Run Code Online (Sandbox Code Playgroud)

界面:

type
  IMyInterface = interface
  ['{B7102C7E-F7F6-492A-982A-4C55CB1065B7}']
    procedure Method2;
  end;
Run Code Online (Sandbox Code Playgroud)

孩子形成:

这个继承自TServerForm并实现接口

type
  TServerForm3 = class(TServerForm, IMyInterface)
  public
    procedure Method1; override;
    procedure Method2;
  end;
Run Code Online (Sandbox Code Playgroud)

这个只是继承自TServerForm

type
  TServerForm4 = class(TServerForm)
  public
    procedure Method1; override;
  end;
Run Code Online (Sandbox Code Playgroud)

这个直接从TForm继承并实现接口

type
  TNoServerForm = class(TForm, IMyInterface)
  public
    procedure Method2;
  end;
Run Code Online (Sandbox Code Playgroud)

所有表单都是自动创建的,然后,我有这个代码来调用OnClick另一个表单上的几个按钮上的方法(应用程序示例的主要形式):

要基于多态调用虚方法:

procedure TForm6.Button1Click(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to Screen.FormCount - 1 do
  begin
    if (Screen.Forms[I] is TServerForm) then
      TServerForm(Screen.Forms[I]).Method1;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

要根据接口的实现调用该方法:

procedure TForm6.Button2Click(Sender: TObject);
var
  I: Integer;
  Intf: IMyInterface;
begin
  for I := 0 to Screen.FormCount - 1 do
  begin
    if Supports(Screen.Forms[I], IMyInterface, Intf) then
      Intf.Method2;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

方法只显示消息,一切正常:

procedure TServerForm3.Method2;
begin
  ShowMessage(ClassName + '.Method2');
end;
Run Code Online (Sandbox Code Playgroud)

  • +1.写得很好,代码片段清楚地显示了差异. (2认同)
  • 没问题.:-)两个小的拼写修复和一个非常小的内嵌代码格式修复. (2认同)