【发布时间】: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 抽象类或具体类,声明任何一种形式的类都支持接口总是有意义的。