How to specify overridden method of which base class to call in Delphi?
Let say, a line of inheritance like this:
TObject -> … SomeMoreBaseClass … -> ParentClass -> MyClass
Suppose ParentClass has no Create(), but it has a Create(int = 0).
Such that when you call ParentClass.Create(), it actually calls ParentClass.Create(0)
Now, in the constructor Create() of MyClass, if I call “inherited;”, I found that I am not getting the ParentClass.Create(0), instead I am getting .Create() of the Base Classes or even TObject.
So, how can I make it to call ParentClass.Create()?
The easiest would be “inherited Create(0)”, but it doesn’t feel “right” enough.
(The ParentClass in my case is actually the System.Generics.Collections.TDictionary)
Code sample:
type
TParentClass = class
public
constructor Create(n:Integer = 0);
end;
TDerivedClass = class(TParentClass)
public
constructor Create; // Note: no parameters
end;
constructor TDerivedClass.Create;
begin
// inherited; // this calls TObject.Create, not TParentClass.Create(0);
inherited Create(0);
end;
First of all, as @Cosmin explains in some detail, the question does not concern overridden methods. The question is about calling inherited methods.
is the best you can do here. This calls the
TDictionary<TKey,TValue>constructor passing the defaultACapacityof0.In fact it may even be preferable to write:
and be quite explicit.
My assumption is that your code looks like this:
I read the documentation for the inherited keyword in an attempt to understand the difference between
inheritedandinherited Create. The best clues are contained in the following excerpts:and
This seems to hint that the two competing uses of
inheritedare treated differently.My understanding is that
inheritedresults in a call to a constructor with matching parameters. In your case,TMyClass<K,V>.Createis parameterless and so the only matching constructor is that ofTObject. Note that none of the constructors ofTDictionarycan match since they all take parameters.On the other hand, when you write
inherited Createthis is a normal method call. And so default parameters can be added to the method call. The crucial point is that this variant allows calling inherited methods with non-matching parameter lists.In my view, the
inheritedsyntax with no following identifier should have been reserved for virtual methods.The designers of
TDictionary<TKey,TValue>could have saved you from this unhappy fate. The constructors ofTDictionary<TKey,TValue>should have been implemented like this:Then the implementation for the parameterless constructor would simply be:
Had this decision been taken, the parameterless constructor declared in
TObjectwould have been hidden from any derived classes and your code would work as you intended.The problem you have encountered here is the result of an unhappy confluence of events involving overloading, default parameters, the parameterless constructor of
TObjectand the quirky syntax ofinheritedfor constructors. Whilst writinginheritedis highly readable and concise, it simply leads to confusion when overloaded methods are in play.