Reputation: 757
I am using a third party reporting VCL package in Delphi 2007. I want to add some code to each of the functions that a couple of objects of this package have. But, I want to do it without having to re-write a lot of code in my application. What I have now is the following:
TBaseReport (Base object with all abstract functions)
|
--------------
| |
TViewReport TPrintReport (Descendents that do the actual implementation of the functions)
The reporting package calls a number of events during the report print process. Each event is passed a TObject parameter with an instance of either a TViewReport (if viewing the report on the screen) or a TPrintReport (if printing directly). For example:
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;
What I would like to do is create a new descendent of TBaseReport (say TMyBaseReport) with some of the same functions overrided to call some of my own code first before calling the inherited code. The problem I have, of course, is that I cannot override TBaseReport because all of it's functions are abstract. So I created two objects to override TViewReport and TPrintReport. Then I tried something like the following:
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;
But the code in TMyReportPrinter and TMyViewReport is never called. Is there anyway to override an object if I don't have any control over the creation of the object to begin with?
Upvotes: 1
Views: 843
Reputation: 53366
I assume PrintText is not defined as a virtual method, so you can't override it.
Maybe there is an event (like OnBeforePrintText) that can be used to add extra functionality.
Else you should redefine some of the functionality.
The difference between static and dynamic linking
When you have a class with two methods and a subclass that overrides one of them:
type
TBaseClass = class
public
procedure MethodA; // Calls MethodB
procedure MethodB;
end;
TSubClass = class (TBaseClass)
public
procedure MethodB;
end;
Now you have an object of TSubClass and call MethodA. Then then MethodB of TBaseClass is called. This is called static linking. MethodB of TSubClass is not called by MethodA of TBaseClass.
But if you declare MethodB as virtual, and use override in TSubClass:
type
TBaseClass = class
public
procedure MethodA; // Calls MethodB
procedure MethodB; virtual;
end;
TSubClass = class (TBaseClass)
public
procedure MethodB; override;
end;
Now MethodB is dynamically linked. So when you call MethodA on an object of class TSubClass, MethodB of TSubClass is called.
Upvotes: 1