我正在使用第三方报告Delphi 2007中的VCL包。我想为这个包的几个对象的每个函数添加一些代码。但是,我想这样做而不必在我的应用程序中重写大量代码。我现在拥有以下内容:
TBaseReport (Base object with all abstract functions)
|
--------------
| |
TViewReport TPrintReport (Descendents that do the actual implementation of the functions)
报告包在报告打印过程中调用了许多事件。每个事件都传递一个TObject参数,其中包含TViewReport(如果在屏幕上查看报告)或TPrintReport(如果直接打印)的实例。例如:
Function TForm1.BeforePrint(Sender: TObject);
Begin
With TBaseReport(Sender) Do // Type cast as TBaseReport so code works with either
Begin // TViewReport or TPrintReport.
.... code here ...
End;
End;
我想要做的是创建TBaseReport的新后代(比如说TMyBaseReport),在调用继承的代码之前,首先调用一些相同的函数来调用我自己的代码。当然,我遇到的问题是我无法覆盖TBaseReport,因为它的所有函数都是抽象的。所以我创建了两个对象来覆盖TViewReport和TPrintReport。然后我尝试了以下内容:
Type
TMyReportPrinter = Class(TReportPrinter)
Public
Procedure PrintText(X, Y: Integer; S: String); Override;
End;
TMyViewReport = Class(TViewReport)
Public
Procedure PrintText(X, Y: Integer; S: String); Override;
End;
.
.
.
Function TForm1.BeforePrint(Sender: TObject);
Var
Rpt: TBaseReport;
Begin
If Sender Is TReportPrinter Then
Rpt := TMyReportPrinter(Sender)
Else
Rpt := TMyViewReport(Sender);
With Rpt Do
Begin
PrintText(1.5, 1.5, 'Foobar');
.... same original code here ...
End;
End;
Procedure TMyReportPrinter.PrintText(X, Y: Integer; S: String);
Begin
Inherited;
LogMsg('PrintText called.');
End;
Procedure TMyViewReport.PrintText(X, Y: Integer; S: String);
Begin
Inherited;
LogMsg('PrintText called.');
End;
但是从未调用过TMyReportPrinter和TMyViewReport中的代码。如果我无法控制对象的创建,那么无论如何都要覆盖一个对象吗?
答案 0 :(得分:1)
我假设PrintText未定义为虚方法,因此您无法覆盖它。
也许有一个事件(如OnBeforePrintText)可以用来添加额外的功能。
否则你应该重新定义一些功能。
静态和动态链接之间的区别
当你有一个有两个方法的类和一个覆盖其中一个的子类时:
type
TBaseClass = class
public
procedure MethodA; // Calls MethodB
procedure MethodB;
end;
TSubClass = class (TBaseClass)
public
procedure MethodB;
end;
现在你有一个TSubClass的对象并调用MethodA。然后调用TBaseClass的MethodB。这称为静态链接。 TSaseClass的MethodB不被方法A的TBaseClass调用。
但是如果将MethodB声明为virtual,并在TSubClass中使用override:
type
TBaseClass = class
public
procedure MethodA; // Calls MethodB
procedure MethodB; virtual;
end;
TSubClass = class (TBaseClass)
public
procedure MethodB; override;
end;
现在MethodB是动态链接的。因此,当您在类TSubClass的对象上调用MethodA时,将调用TSubClass的MethodB。