【问题标题】:calling methods of a class inherited form an interface and another ancestor调用从接口和另一个祖先继承的类的方法
【发布时间】:2013-02-06 02:30:09
【问题描述】:

我在实现某些类之间的关系时遇到问题。我得到了三个不同的课程,提供三种不同的形式。所有这些类都使用相同的语言,因此它们继承自同一个名为TAncestorServer 的类。我们称它的后代为TForm1ServerTForm2ServerTForm3ServerTAncestorServer 包含一个名为Function1 的抽象方法,因此TForm1TForm2TForm3 可以通过从它继承的自己的类毫无问题地调用它,它们可以通过名为的属性访问这些类Server。但问题在于另一种形式,称为TForm4!它与其他形式非常相似,但不像它们那样独立。它适用于TForm2ServerTForm3Server。仍然不是问题,但想象另一种方法,如Function2,在TForm2ServerTForm3Server 中声明,TForm4 需要调用它们。我可以这样走:

if Server is TForm2Server then
   TForm2Server(Server).Function2
else if Server is TForm3Server then
  TForm3Server(Server).Function2;

但它可以变成无限的 if-else 子句!所以我认为像多重继承这样的东西可能会有所帮助。我声明了一个名为IForm4Server 的接口,其中包含Function2。所以TForm2ServerTForm3Server 继承自TAncestorServerIForm4Server。我认为这样的事情可以工作:

If Server is IForm4Server then
  IForm4Server(Server).Function2;

但是编译器不这么认为,它说它不是一个有效的类型转换,因为TAncestorServer 不是IForm4Server,这是绝对正确的。 TForm1Server 不知道如何实现 Function2,必须将其留空。我也不能将TForm4.Server 声明为IForm4Server,因为Function1 代表了大量的方法和属性,但是我仍然无法将IForm4Server 类型转换为TAncestorServer

作为一种解决方案,我可以在TForm4 中定义两个不同的属性,例如GeneralServer: TAncestorServerForm4Server: IForm4Server,然后将TForm2ServerTForm3Server 的相同实例分配给它们,但我对此感觉不太好。我该怎么做?它有什么标准模式吗?

【问题讨论】:

  • 关于你的问题的标题,接口不是你类的祖先。 Delphi 仅支持单继承(您似乎知道),因此每个班级只有一个父亲/祖父......等等。因此,您只能从祖先那里继承方法。您的类可以实现任意数量的接口,但这些接口不是您的类的祖先,只是它实现的接口。
  • 感谢指正。我在使用界面和用英语提问方面都是新手!任何建议将不胜感激。

标签: delphi oop interface multiple-inheritance


【解决方案1】:

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

基本的东西是:

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

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

共同祖先类:

type
  TServerForm = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
    procedure Method1; virtual;
  end;

界面:

type
  IMyInterface = interface
  ['{B7102C7E-F7F6-492A-982A-4C55CB1065B7}']
    procedure Method2;
  end;

子窗体:

这个继承自TServerForm并实现接口

type
  TServerForm3 = class(TServerForm, IMyInterface)
  public
    procedure Method1; override;
    procedure Method2;
  end;

这个只是继承自 TServerForm

type
  TServerForm4 = class(TServerForm)
  public
    procedure Method1; override;
  end;

而这个直接继承自TForm并实现接口

type
  TNoServerForm = class(TForm, IMyInterface)
  public
    procedure Method2;
  end;

所有的表单都是自动创建的,然后,我有这段代码可以调用一对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;

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

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;

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

procedure TServerForm3.Method2;
begin
  ShowMessage(ClassName + '.Method2');
end;

【讨论】:

  • +1。写得很好,代码 sn-ps 清楚地显示了差异。
  • 没问题。 :-) 两个小的拼写修复和一个非常小的内联代码格式修复。
猜你喜欢
  • 2011-06-07
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2010-09-06
  • 2013-05-08
  • 2012-08-29
  • 2014-04-18
相关资源
最近更新 更多