After having read Ian Boyd's constructor series questions (1, 2, 3, 4), I realize I don't quite grasp the literal meaning on what's being hidden.
I know (correct me if I'm wrong) override
's sole purpose is to be able to have polymorphic behavior, so that run-time can resolve a method depending on the actual type of an instance - as opposed to the declared type. Consider the following code:
type
TBase = class
procedure Proc1; virtual;
procedure Proc2; virtual;
end;
TChild = class(TBase)
procedure Proc1; override;
procedure Proc2; // <- [DCC Warning]
end;
procedure TBase.Proc1;
begin
Writeln('Base.Proc1');
end;
procedure TBase.Proc2;
begin
Writeln('Base.Proc2');
end;
procedure TChild.Proc1;
begin
inherited Proc1;
Writeln('Child.Proc1');
end;
procedure TChild.Proc2;
begin
inherited Proc2;
Writeln('Child.Proc2');
end;
var
Base: TBase;
begin
Base := TChild.Create;
Base.Proc1;
Writeln;
Base.Proc2;
Base.Free;
Readln;
end.
Which outputs:
Base.Proc1
Child.Proc1
Base.Proc2
The warning on TChild.Proc2
states that this method "will hide access to the base's method of the same name". What I see is, if I don't override Proc2
I loose the ability of the method's resolving to its actual type, not of its base type. How's that hiding access to base's method?
Further, down the documentation on the warning as a solution to the warning, it is stated that:
First, you could specify override to make the derived class' procedure also virtual, and thus allowing inherited calls to still reference the original procedure.
Now, if I create a 'TChild' instance from a 'TChild' (no polymorphism), the inherited call in the non-overridden method clearly refers to the original procedure. If I create the 'Child' instance from a 'TBase', the call does not even resolve to a 'TChild' method, how could I call 'Inherited' that would refer to anything at all?
What am I misunderstanding?
Amongs other thing, you won't be able to define
TGrandChild = class(TChild)
procedure Proc2; override;
end;
because Proc2 that TGrandChild sees is the one from TChild that is not virtual. The TChild.Proc2 hide TBase.Proc2 from descendants.
EDIT:
In answer to Sertac's comment:
var
Base: TBase;
Child : TChild
begin
Child := TChild.Create;
Base := Child;
Base.Proc2;
Child.Proc2;
Base.Free;
Readln;
That will output
Base.Proc2
Base.Proc2
Child.Proc2
So, what seems to be a call to the same method twice is actually a call to 2 different methods. That makes code harder to understand (which is not practical) and yield unexpected behavior.
You are thinking too complicated. Hiding doesn't mean you completely lose access to the original. It simply means (and you already noted this yourself) if you have an object of static type TChild, and you call Proc2 on it, it calls the one in TChild, and not the one in TBase. Also what Ken said is true.
It is warning you because the original is virtual and hiding is most likely not what people intend when writing code like that. At the very least it's bad coding style.
Use 'reintroduce' to suppress the warning.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With