【问题标题】:Why doesn't the descendent's version of an abstract base class's method get called?为什么不调用抽象基类方法的后代版本?
【发布时间】:2011-12-15 15:20:11
【问题描述】:

我正在尝试创建一个简单的 THistory 类,它有一个过程,该过程采用实现简单接口的抽象基类。

下面的代码可以编译,但是THistory类调用了基类HistoryRecords abstract Insert proc,而不是传入的子类Insert proc。我错过了什么?

感谢您的帮助!

unit uHistory;

interface

uses Dialogs;

type

IHistoryRecord = interface
  ['{67C90064-1667-4DE0-AF52-11B6E5A00892}']
  procedure Insert();
end;

THistoryRecord = class abstract(TInterfacedObject, IHistoryRecord)
  procedure Insert(); virtual; abstract;
end;

THistory = class(TObject)
  public
  procedure Add(pHistoryRecord : THistoryRecord);
end;

TAlarmHistoryRecord = class(THistoryRecord)
  procedure Insert();
end;

implementation

{ THistory }

procedure THistory.Add(pHistoryRecord: THistoryRecord);
begin
  pHistoryRecord.Insert();
end;

{ TAlarmHistoryRecord }

procedure TAlarmHistoryRecord.Insert;
begin
  MessageDlg('Alarm History Record - Insert Method', mtInformation, [mbOK], 0);
end;

end.

Usage
procedure TForm1.Button1Click(Sender: TObject);
var
  lHistory : THistory;
  lHistoryRecord : TAlarmHistoryRecord;
begin

  lHistory := THistory.Create();

  lHistoryRecord := TAlarmHistoryRecord.Create();

  // I want this to call the TAlarmsHistoryRecord.Insert proc not the
  // HistoryRecord base class Insert proc.
  lHistory.Add(lHistoryRecord);

end;

【问题讨论】:

  • 抽象类实现接口是设计废话。使用抽象类或接口,而不是两者。
  • 在这种情况下,@Serg,你是对的:由于 THistoryRecord 只有一个方法,并且没有实现,因此从该方法下降而不是直接实现 IHistoryRecord 没有任何优势。但是,在其他情况下,抽象类为接口的 part 提供默认实现可能很有用,因此后代可以只专门化必要的部分。 TInterfacedObject 就是一个很好的例子;它实现了 IUnknown 的细节,因此其他类不必这样做,但没有理由直接实例化 TInterfacedObject,所以它本质上是抽象的。
  • 另一方面,由于接口类型从未在代码的可执行部分中引用 - 仅在基类声明中 - 它与这个问题并不真正相关。没有任何东西可以通过接口访问类,所以接口是一条红鲱鱼。
  • @Rob 正如你所说的 TInterfacedObject implements IUnknown 方法。设计废话就是将这些方法声明为virtual; abstract。我认为没有理由这样做。
  • @Serg 抽象类或具体类,声明任何一种形式的类都支持接口总是有意义的。

标签: delphi interface abstract


【解决方案1】:

您错过了覆盖

TAlarmHistoryRecord = class(THistoryRecord)
  procedure Insert(); override;
end;

【讨论】:

    【解决方案2】:

    您在TAlarmHistoryRecord 方法声明中缺少override 指令,即它应该是

    procedure Insert(); override;
    

    实际上编译器应该警告你该方法隐藏了继承的。

    【讨论】:

    • 对不起,你回答有点晚了
    • 不仅应该有一个关于隐藏基类的虚方法的警告,而且应该有一个关于实例化仍然有抽象方法的类的警告! 永远不要忽略编译器警告,肖恩。
    • 当然,您必须先启用提示和警告才能看到它们。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 2021-08-07
    • 2011-07-08
    • 2019-04-19
    • 1970-01-01
    相关资源
    最近更新 更多