Safe way in Delphi for a Form to distribute interface objects tied to its lifetime? - delphi

I have a Delphi Form that provides the functionality behind an interface object that other parts of the code get references too via a property belonging to the Form. I can't delegate the interface functionality to a child object because too much of that functionality is serviced by controls/components on the form. I can't use TAggregatedObject or TContainedObject to link the lifetime of the interfaced objects being passed around to the Form because the TForm class does not inherit from TinterfacedObject and Delphi does not support multiple inheritance so I can't mix in TInterfacedObject into the inheritance chain. This situation can lead to access violations if a Form gets destroyed while some other code holds one of the interface references passed out by the Form. Can anyone think of a good solution to this problem?

You can delegate the interface to a child object, just have that object contain an internal pointer to the Form so it can access the Form's controls when needed, no different then you are already doing right now.
You can use TAggregateObject or TContainedObject for your needs. They do not require the Form to derive from TInterfacedObject. All they do require is an IInterface interface pointer, and TComponent derives from IInterface (and overrides the _AddRef() and _Release() to disable reference counting), so you can pass the Form itself (being a TComponent descendant) as the required IInterface pointer.
That leaves the only issue remaining - the Form closing while active interface references are being held by other code. The simpliest solution is to either 1) rewrite that code to not hold on to those references while the Form is closing, or 2) don't allow the Form to close until those references have been released.

Note: This will only work, if your consumer is also derived from TComponent.
To avoid the dead references you can query the IInterfaceComponentReference (available on every TComponent) from your form, call GetComponent on that interface and attach yourself to the FreeNotification of the returned Component/Form.
What happens now is: When the Form gets destroyed it will notify all "listners" that its going to destroy itself by calling the Notification method on the consumer with itself (form) as AComponent and opRemove as operation. Thus allowing you to nil your interface reference.
But be aware that the object references and interface references must not be equal.
Also make sure to call RemoveFreeNotification when you don't need the Notification any more to avoid unnecessary calls.
TSomeConsumer = class(TComponent)
private
FInterfaceToAService: ISomeInterface;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
procedure SetService(const Value: ISomeInterface);
end;
procedure TSomeConsumer.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = TObject(FInterfaceToAService)) then
SetService(nil); // Takes care of niling the interface as well.
end;
procedure TSomeConsumer.SetService(const Value: ISomeInterface);
var
comRef: IInterfaceComponentReference;
begin
if Supports(FInterfaceToAService, IInterfaceComponentReference, comRef) then
comRef.GetComponent.RemoveFreeNotification(self);
FInterfaceToAService := Value;
if Supports(FInterfaceToAService, IInterfaceComponentReference, comRef) then
comRef.GetComponent.FreeNotification(self);
end;

Related

Freeing interfaced object that descends from a TRectangle

I'm new to interfaces and have been trying them out in my latest project. I have this (simplified) interface:
IBoardShape = interface(IInterface)
function GetColor: integer;
procedure SetColor(const aColor: integer);
property Color: integer read GetColor write SetColor;
end;
Several classes descend from it like so:
TGameRectangle = class(TRectangle, IBoardShape)
private
FColor: integer;
function GetColor: integer;
procedure SetColor(const aColor: integer);
property Color: integer read GetColor write SetColor;
end;
I have a factory for creating the shapes in its own data module.
function TdmShapeManager.CreateRect(aParent: TLayout): IBoardShape;
var
lRect: TGameRectangle;
begin
lRect := TGameRectangle.Create(self);
lRect.Parent := aParent;
lRect.Align := TAlignLayout.alClient;
result := lRect as IBoardShape;
end;
The result is added to a TList<IBoardShape>.
All of this worked well, until I started trying to remove shapes at run time. I found that TList[I] := nil didn't free the item, the control would just stay on the screen. So, from here I'm not sure to do. I found I can cast the object to a TShape and call .Free on it, but that doesn't sound right. (I tried it and it works but then it leads to other problems - errors inside Delphi code when trying to free an interface.)
One thing that I'm not sure about: Since my TGameRectangle doesn't descend from TInterfacedObject, should I be doing my own reference counting? Or am I misunderstanding what TInterfacedObject is for?
I'm going to restrict my answer to desktop platforms which do not have ARC. That's because on ARC platforms there is nothing to do. The ARC framework will manage lifetime for you and you must not re-implement _AddRef and _Release.
For non-ARC platforms you have a fundamental design problem. You want your object's lifetime to be controlled by two independent mechanisms:
The TComponent owner, and
The interface reference count.
You need to make up your mind to do it one way or the other. But not both.
If you opt for the first option you just need to make sure that you clear the interface reference before the owner is destroyed. Then let the owner destroy your rectangle object.
If you opt for the second option you need to pass nil as the owner parameter of the constructor. And then implement interface reference counted lifetime management as per TInterfacedObject.
A common pattern is to let the value of the owner passed to the constructor determine the lifetime model. So, when the owner is nil, interface reference counting controls the life. Otherwise the owner controls it. The canonical example of this pattern is TXMLDocument.
All that said, I don't think this pattern works at well with visual components. The framework is designed so that visual component lifetime is not controlled by interface reference counting. I think it is folly to go against that design. I suggest you opt for option 1.
Yes, if you want to use interfaces and reference counting, you need to either inherit from a type that provides reference counting or provide your own implementations of _AddRef and _Release.
What do the _AddRef and _Release that your TGameRectangle has do?

How can I change the owner of a DataModule after creation?

I am trying to pass a DataModule to a form in the form's constructor. I also want the form to be the "Owner" of the DataModule so that the form will destroy the DataModule when it is closed. That creates the problem of both objects needing each other in their constructors.
I tried to set the owner of the DataModule after creation but that is a read only property.
My second form looks like this:
type
TSecondPopup = class(TForm)
private
FMyData: TMyData;
public
constructor Create(MyData: TMyData); reintroduce;
end;
var
SecondPopup: TSecondPopup;
implementation
{$R *.dfm}
constructor TSecondPopup.Create(MyData: TMyData);
begin
FMyData := MyData;
inherited Create(nil);
end;
There is no special code in my data module.
In my main form I want to do something like this when showing the second form:
procedure TMainApp.Button1Click(Sender: TObject);
var
MyData: TMyData;
SecondPopup: TSecondPopup;
begin
MyData := TMyData.Create(nil);
SecondPopup := TSecondPopup.Create(MyData);
// Can't change owner now. It is a read only property.
// MyData.Owner := SecondPopup;
SecondPopup.Show;
end;
I know I can change the DataModule to be a property on the form. Then I could create the form first, then create the data module setting the owner, and finally set the property on the form. I am trying to use constructor dependency injection on this project. It had been working great when I had a shared data module that the main form passed to multiple forms. In that case the main form holds on to the data module until it exists. In this case there is only one form that needs this data module so I wanted to force it to manage the life of the data module by setting the owner.
Another option would be to explicitly free the DataModule when I close the second form. However that form has no way of knowing if the caller also passed the datamodule to a different form.
Is there a way to use the constructor to inject my object but still get the form to manage the lifetime?
Currently using Delphi XE3.
Changing ownership of a component is possible with NewOwner.InsertComponent(TheComponent). And since a component can only be owned by one component at a time, the RTL takes care of removing ownership from the previous owner automatically.
But...
Another option would be to explicitly free the DataModule when I close the second form. However that form has no way of knowing if the caller also passed the datamodule to a different form.
If you want the possibility to pass a single DataModule to multiple Forms, then changing ownership of the DataModule is not the solution: the one Form that owns the DataModule will not be able to deside whether it may free the DataModule. Thus the conclusion is that the DataModule cannot be owned by any form, except by the MainForm. (Then I would prefer to let it own by the Application object, but that's a matter of taste.)
Subsequently, you will then need a reference counting mechanism within the DataModule for the Forms which it is attached to.
You don't have to change the DataModule's Owner. You can simply destroy the DataModule whenever you want, even if it has an Owner assigned. When the DataModule is freed, it will simply remove itself from its Owner so it is not freed a second time. If you go this approach, you should also add a call to FreeNotification() so that you are notified if the DataModule gets freed (by its Owner or anyone else) while your form is still referencing it:
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
constructor TSecondPopup.Create(MyData: TMyData);
begin
inherited Create(nil);
FMyData := MyData;
if FMyData <> nil then
FMyData.FreeNotification(Self);
end;
destructor TSecondPopup.Destroy;
begin
if FMyData <> nil then
FMyData.RemoveFreeNotification(Self);
inherited Destroy;
end;
procedure TSecondPopup.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (AComponent = FMyData) then
FMyData := nil;
end;
If you absolutely want to change the DataModule's Owner, that is also doable, via the TComponent.RemoveComponent() and TComponent.InsertComponent() methods:
constructor TSecondPopup.Create(MyData: TMyData);
begin
inherited Create(nil);
FMyData := MyData;
if FMyData <> nil then
begin
// InsertComponent() will call RemoveComponent() internally for you...
Self.InsertComponent(FMyData);
end;
end;
You want to let the form own the data module. Since ownership is most naturally specified at construction time, then the conclusion is that the form should be created first.
So, instead of passing the data module to the form's constructor, pass something that allows the form to invoke the instantiation of the data module. For instance, you could pass a function to the form's constructor that accepts the form as a parameter and returns the newly minted data module. For instance.
type
TCreateDataModule = function(Owner: TMyForm): TMyDataModule of object;
You could perfectly well create the data module outside the form but with no owner. That pass the object to the form constructor. The form can then destroy the data module in its destructor. That sounds the cleanest solution to me. I find it hard to see past this option.
I think you considered this option already but rejected it with this reasoning:
However that form has no way of knowing if the caller also passed the data module to a different form.
If that is so, then nothing can save you. You cannot have two objects both in charge of the lifetime, unless they use reference counting or similar.
Why create a Data Module that is meant to be used by a form, prior to creating the form?
1) Why not just add the Data Module unit to the interface uses list of the form, declare a private variable of the Data Module type in the form, and create the form's Data Module variable in the OnCreate event of the form...and then you can FreeAndNil the Data Module in the OnDestroy event.
Additionally, you can further declare a public property of the form's Data Module variable, with which you can access the Data Module from the calling unit (i.e. TestForm.DataModule)
2) If you are thinking you must create the Data Module outside of the form, perhaps to do a great number of Data Module-involved initializations, processes, etc. first, and then passing the Data Module off to the form and forgetting about it ... and assuming this form you are creating, that will be utilizing the Data Module, will be a NON-modal form (that bit of information would be of great help), you could always do 1) {above} first, then access the 'TestForm.DataModule' to apply all of your initializations, processes, etc. to before calling the form's Show method.

How to free an object which is in a record?

Here I have a tricky situation, I guess. I need to be able to free an object which is a field of a record. I would normally write the cleanup code in the destructor, if it was a class. But since record types can't introduce a "destructor", how would it be possible to call TObject(Field).Free; ?
There'll be two types of usage I predict:
Replacing the record with a new one.
I think this usage would be easy to implement. Since records are value types and so they are copied on assignment, I can overload the assigning operator and free the objects owned by old record.
( Edit: Assignment overloading wasn't able. That's a new info to me.. )
Exiting the scope where record variable defined.
I can think of a private method that frees the objects and this method could be called on scope excitation manually. BUT, here is the same question: How to make it more recordly? This behaviour kind of feels like a class...
Here is a sample (and obviously not the intended usage):
TProperties = record
... some other spesific typed fields: Integers, pointers etc..
FBaseData: Pointer;
FAdditionalData: TList<Pointer>;
//FAdditionalData: array of Pointer; this was the first intended definition
end;
Assume,
FAdditionalData:=TList<Pointer>.Crete;
called in record constructor or manually in record variable scope by accessing the field publicly like
procedure TFormX.ButtonXClick(Sender: TObject);
var
rec: TProperties;
begin
//rec:=TProperties.Create(with some parameters);
rec.FAdditionalData:=TList<Pointer>.Create;
//do some work with rec
end;
After exiting the ButtonClick scope the rec is no more but a TList still keeps its existance which causes to memory leaks...
If all you have in the record is an object reference, then you can't get the compiler to help you. You are in sole charge of the lifetime of that object. You cannot overload the assignment operator, and you don't get any notification of scope finalisation.
What you can do though is to add a guard interface that will manage the lifetime of the object.
TMyRecord = record
obj: TMyObject;
guard: IInterface;
end;
You need to make sure that TMyObject manages its lifetime by reference counting. For example by deriving from TInterfacedObject.
When you initialise the record you do this:
rec.obj := TMyObject.Create;
rec.guard := rec.obj;
At this point, the guard field of the record will now manage your object's lifetime.
In fact, if you want to push this idea further, you can build a dedicated class to guard the lifetime of objects. That then no longer constrains you to implement IInterface on your class. There are plenty of examples on the web that illustrate the technique. For example I offer Jarrod Hollingworth's article titled Smart Pointers, and Barry Kelly's titled Reference-counted pointers, revisited. There are many more out there. It's an old trick!
Note however, that what you have here is a strange hybrid of value type and reference type. On the face of it, records are value types. However, this one acts like a reference type. If you have other fields in the record that are value types then that would be even more confusing. You'll need to be very aware of this issue when you work with such a record.
On the face of it, without knowing more about your design, I'd be inclined to advise you not to put object references in records. They fit better inside reference types, i.e. classes.
I remember that someone created a class named TLifetimeWatcher. Basically, it looks like:
TLifetimeWatcher = class(TInterfacedObject)
private
fInstance: TObject;
fProc: TProc;
public
constructor Create(instance: TObject); overload;
constructor Create(instance: TObject; proc: TProc); overload;
destructor Destroy; override;
end;
// The (cleanup) proc will be executed in the destructor if assigned, otherwise the instance will be freed by invoking the Free method.
https://docwiki.embarcadero.com/RADStudio/Sydney/en/Custom_Managed_Records
THeaderStruct = record
private
public
class operator Initialize (out Header: THeaderStruct);
class operator Finalize (var Header: THeaderStruct);
end;

Using inherited in the "Create" constructor of an TObject

Rant: Should I call "inherited" in the constructor of a class derived from TObject or TPersistent?
constructor TMyObject.Create;
begin
inherited Create; // Delphi doc: Do not create instances of TPersistent. Use TPersistent as a base class when declaring objects that are not components, but that need to be saved to a stream or have their properties assigned to other objects.
VectorNames := TStringList.Create;
Clear;
end;
Yes. It does nothing, true, but it's harmless. I think there is value in being consistent about always calling the inherited constructor, without checking to see if there is, in fact, an implementation. Some will say that it's worth calling inherited Create because Embarcadero might add an implementation for TObject.Create in the future, but I doubt this is true; it would break existing code which does not call inherited Create. Still, I think it is a good idea to call it for the reason of consistency alone.
I always do this.
If you are refactoring and move code to a common ancestor, calling the inherited Create has the following advantages:
If the common ancestor has a constructor, you can't forget to call it.
If the common ancestor has a constructor with different parameters, the compiler warns you for this.
You can also override "procedure AfterConstruction". This procedure is always called, no matter what kind of constructor.
public
procedure AfterConstruction; override;
end;
procedure TfrmListBase.AfterConstruction;
begin
inherited;
//your stuff, always initialized, no matter what kind of constructor!
end;
For example: if you want to create an object with a different constructor than the normal TObject.Create, such as TComponent.Create(AOwner) or a custom (overloaded) constructor, you can get problems because your override is not called and (in this case) your "VectorNames" variable will be nil.
I call it, except when i need a very optimized constructor.

Reintroducing functions in Delphi

What was the motivation for having the reintroduce keyword in Delphi?
If you have a child class that contains a function with the same name as a virtual function in the parent class and it is not declared with the override modifier then it is a compile error. Adding the reintroduce modifier in such situations fixes the error, but I have never grasped the reasoning for the compile error.
If you declare a method in a descendant class that has the same name as a method in an ancestor class then you are hiding that ancestor method — meaning if you have an instance of that descendant class (that is referenced as that class) then you will not get the behavior of the ancestor. When the ancestor's method is virtual or dynamic, the compiler will give you a warning.
Now you have one of two choices to suppress that warning message:
Adding the keyword reintroduce just tells the compiler you know you are hiding that method and it suppresses the warning. You can still use the inherited keyword within your implementation of that descended method to call the ancestor method.
If the ancestor's method was virtual or dynamic then you can use override. It has the added behavior that if this descendant object is accessed through an expression of the ancestor type, then the call to that method will still be to the descendant method (which then may optionally call the ancestor through inherited).
So difference between override and reintroduce is in polymorphism. With reintroduce, if you cast the descendant object as the parent type, then call that method you will get the ancestor method, but if you access it the descendant type then you will get the behavior of the descendant. With override you always get the descendant. If the ancestor method was neither virtual nor dynamic, then reintroduce does not apply because that behavior is implicit. (Actually you could use a class helper, but we won't go there now.)
In spite of what Malach said, you can still call inherited in a reintroduced method, even if the parent was neither virtual nor dynamic.
Essentially reintroduce is just like override, but it works with non-dynamic and non-virtual methods, and it does not replace the behavior if the object instance is accessed via an expression of the ancestor type.
Further Explanation:
Reintroduce is a way of communicating intent to the compiler that you did not make an error. We override a method in an ancestor with the override keyword, but it requires that the ancestor method be virtual or dynamic, and that you want the behavior to change when the object is accessed as the ancestor class. Now enter reintroduce. It lets you tell the compiler that you did not accidentally create a method with the same name as a virtual or dynamic ancestor method (which would be annoying if the compiler didn't warn you about).
There are lots of answers here about why a compiler that lets you hide a member function silently is a bad idea. But no modern compiler silently hides member functions. Even in C++, where it's allowed to do so, there's always a warning about it, and that ought to be enough.
So why require "reintroduce"? The main reason is that this is the sort of bug that can actually appear by accident, when you're not looking at compiler warnings anymore. For example, let's say you're inheriting from TComponent, and the Delphi designers add a new virtual function to TComponent. The bad news is your derived component, which you wrote five years ago and distributed to others, already has a function with that name.
If the compiler just accepted that situation, some end user might recompile your component, ignore the warning. Strange things would happen, and you would get blamed. This requires them to explicitly accept that the function is not the same function.
The RTL uses reintroduce to hide inherited constructors. For example, TComponent has a constructor which takes one argument. But, TObject has a parameterless constructor. The RTL would like you to use only TComponent's one-argument constructor, and not the parameterless constructor inherited from TObject when instantiating a new TComponent. So it uses reintroduce to hide the inherited constructor. In this way, reintroduce is a little bit like declaring a parameterless constructor as private in C#.
First of all, "reintroduce" breaks the inheritance chain and should not be used, and I mean never ever. In my entire time I worked with Delphi (ca 10 years) I've stumbled upon a number of places that do use this keyword and it has always been a mistake in the design.
With that in mind here's the simplest way it works:
You have like a virtual method in a base class
Now you wanna have a method that has the exact same name, but maybe a different signature. So you write your method in the derived class with the same name and it will not compile because the contract is not fulfilled.
You put the reintroduce keyword in there and your base class does not know about your brand new implementation and you can use it only when accessing your object from a directly specified instance type. What that means is toy can't just assign the object to a variable of base type and call that method because it's not there with the broken contract.
Like I said it's pure evil and must be avoided at all cost (well, that's my opinion at least). It's like using goto - just a terrible style :D
The purpose of the reintroduce modifier is to prevent against a common logical error.
I will assume that it is common knowledge how the reintroduce keyword fixes the warning and will explain why the warning is generated and why the keyword is included in the language. Consider the delphi code below;
TParent = Class
Public
Procedure Procedure1(I : Integer); Virtual;
Procedure Procedure2(I : Integer);
Procedure Procedure3(I : Integer); Virtual;
End;
TChild = Class(TParent)
Public
Procedure Procedure1(I : Integer);
Procedure Procedure2(I : Integer);
Procedure Procedure3(I : Integer); Override;
Procedure Setup(I : Integer);
End;
procedure TParent.Procedure1(I: Integer);
begin
WriteLn('TParent.Procedure1');
end;
procedure TParent.Procedure2(I: Integer);
begin
WriteLn('TParent.Procedure2');
end;
procedure TChild.Procedure1(I: Integer);
begin
WriteLn('TChild.Procedure1');
end;
procedure TChild.Procedure2(I: Integer);
begin
WriteLn('TChild.Procedure2');
end;
procedure TChild.Setup(I : Integer);
begin
WriteLn('TChild.Setup');
end;
Procedure Test;
Var
Child : TChild;
Parent : TParent;
Begin
Child := TChild.Create;
Child.Procedure1(1); // outputs TChild.Procedure1
Child.Procedure2(1); // outputs TChild.Procedure2
Parent := Child;
Parent.Procedure1(1); // outputs TParent.Procedure1
Parent.Procedure2(1); // outputs TParent.Procedure2
End;
Given the above code both of the procedures in TParent are hidden. To say they are hidden means that the procedures can not be called through the TChild pointer. Compiling the code sample produces a single warning;
[DCC Warning] Project9.dpr(19): W1010 Method 'Procedure1' hides virtual method of base type 'TParent'
Why only a warning for the virtual function and not the other? Both are hidden.
A virtue of Delphi is that library designers are able to release new versions without fear of breaking the logic of existing client code. This contrasts to Java where adding new functions to a parent class in a library is fraught with danger because classes are implicitly virtual. Lets say that TParent from above lives in a 3rd party library, and the library manufacture releases the new version below.
// version 2.0
TParent = Class
Public
Procedure Procedure1(I : Integer); Virtual;
Procedure Procedure2(I : Integer);
Procedure Procedure3(I : Integer); Virtual;
Procedure Setup(I : Integer); Virtual;
End;
procedure TParent.Setup(I: Integer);
begin
// important code
end;
Imagine we had the following code in our client code
Procedure TestClient;
Var
Child : TChild;
Begin
Child := TChild.Create;
Child.Setup;
End;
For the client it does not matter if the code is compiled against version 2 or 1 of the library, in both cases TChild.Setup is called as the user intends. And in the library;
// library version 2.0
Procedure TestLibrary(Parent : TParent);
Begin
Parent.Setup;
End;
If TestLibrary is called with a TChild parameter, everything works as intended. The library designer have no knowledge of the TChild.Setup, and in Delphi this does not cause them any harm. The call above correctly resolves to TParent.Setup.
What would happen in a equivalent situation in Java? TestClient would work correctly as intended. TestLibrary would not. In Java all functions are assumed virtual. The Parent.Setup would resolve to TChild.Setup, but remember when TChild.Setup was written they had no knowledge of the future TParent.Setup, so they are certainly not going to ever call inherited. So if the library designer intended TParent.Setup to be called it will not be, no matter what they do. And certainly this could be catasrophic.
So the object model in Delphi requires explicit declaration of virtual functions down the chain of child classes. A side effect of this is that it is easy to forget to add the override modifier on child methods. The existence of the Reintroduce keyword is a convenience to the programmer. Delphi was designed so that the programmer is gently persuaded, by the generation of a warning, to explicitly state their intentions in such situations.
tl;dr: Trying to override a non-virtual method makes no sense. Add the keyword reintroduce to acknowledge that you're making a mistake.
Reintroduce tells the compiler you want to call the code defined in this method as an entry point for this class and its descendants, regardless of other methods with the same name in the ancestors’ chain.
Creating a TDescendant.MyMethod would create a potential confusion for the TDescendants in adding another method with the same name, which the compiler warns you about.
Reintroduce disambiguates that and tells the compiler you know which one to use.
ADescendant.MyMethod calls the TDescendant one, (ADescendant as TAncestor).MyMethod calls the TAncestor one. Always! No confusion…. Compiler happy!
This is true whether you want the descendant method to be virtual or not: in both cases you want to break the natural linkage of the virtual chain.
And it does not prevent you from calling the inherited code from within the new method.
TDescendant.MyMethod is virtual: ...but you cannot or don’t want to use the linkage.
You cannot because the method signature is different. You have no other choice as overriding is impossible in this case with return type or parameters not exactly the same.
You want to restart an inheritance tree from this class.
TDescendant.MyMethod is not virtual: You turn MyMethod into a static one at the TDescendant level and prevent further overriding. All classes inheriting from TDescendant will use the TDescendant implementation.
When the ancestor class also has a method with the same name, and it is not necessarily declared virtual, you would see a compiler warning (as you would hide this method).
In other words: You tell the compiler that you know that you hide the ancestor function and replace it with this new function and do so deliberately.
And why would you do this? If the method is virtual in the parent class, the only reason is to prevent polymorphism. Other then that just override and do not call inherited. But if the parent method is not declared virtual (and you cannot change that, because you do not own the code for example), you can inherit from that class and let people inherit from your class without seeing a compiler warning.
This has been introduced to the language because of Framework versions (including the VCL).
If you have an existing code base, and an update to a Framework (for instance because you bought a newer Delphi version) introduced a virtual method with the same name as a method in an ancestor of your code base, then reintroduce will allow you to get rid of the W1010 warning.
This is the only place where you should use reintroduce.
First, as it was said above, you should never ever deliberately reintroduce virtual method. The only sane use of reintroduce is when the author of the ancestor (not you) added a method that goes into conflict with your descendant and renaming your descendant method is not an option. Second, you can easily call the original version of the virtual method even in classes where you reintroduced it with different parameters:
type
tMyFooClass = class of tMyFoo;
tMyFoo = class
constructor Create; virtual;
end;
tMyFooDescendant = class(tMyFoo)
constructor Create(a: Integer); reintroduce;
end;
procedure .......
var
tmp: tMyFooClass;
begin
// Create tMyFooDescendant instance one way
tmp := tMyFooDescendant;
with tmp.Create do // please note no a: integer argument needed here
try
{ do something }
finally
free;
end;
// Create tMyFooDescendant instance the other way
with tMyFooDescendant.Create(20) do // a: integer argument IS needed here
try
{ do something }
finally
free;
end;
so what should be the purpose of reintroducing virtual method other than make things harder to read?
reintroduce allows you to declare a method with the same name as the ancestor, but with different parameters. It has nothing to do with bugs or mistakes!!!
For example, I often use it for constructors...
constructor Create (AOwner : TComponent; AParent : TComponent); reintroduce;
This allows me to create the internal classes in a cleaner fashion for complex controls such as toolbars or calendars. I normally have more parameters than that. Sometimes it is almost impossible or very messy to create a class without passing some parameters.
For visual controls, Application.Processmessages can get called after Create, which can be too late to use these parameters.
constructor TClassname.Create (AOwner : TComponent; AParent : TComponent);
begin
inherited Create (AOwner);
Parent := AParent;
..
end;

Resources