Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi unexpected behavior of override

Tags:

theory

delphi

Turn on your time machine and visit ancient times: It's Delphi and it is 2007.

For our beginners handbook I write down some basic things of programming (with Delphi). Doing so I found a quirk, I don't quite understand. To demonstrate inheritance I wrote a base class and a heir of it. A function is reintroduced, the other is overridden by the Heir.

unit UOverride;
interface
type
Base = class(TObject)
  strict private
    const
      CName: String = 'Base-Class';
      CMaxim: String = 'Somebody set up us the bomb.';
  public
    function GetName(): String; virtual;
    function GetMaxim(): String; virtual;

end;

Heir = class(Base)
  strict private
    const
      CName: String = 'Heir-Class';
      CMaxim: String = 'All your Base are belong to us!';
  public
    function GetName(): String; reintroduce;
    function GetMaxim(): String; override;
    function GetBaseName(): String;
    function GetBaseMaxim():String;
end;

implementation
{ Base }
function Base.GetMaxim: String;
begin
  Result := CMaxim;
end;

function Base.GetName: String;
begin
  Result := CName;
end;

{ Heir }
function Heir.GetMaxim: String;
begin
  Result := CMaxim;
end;

function Heir.GetName: String;
begin
  Result := CName;
end;

end.

So when I create an object of Base and call the too functions, it works as expected:

  • GetName() => Base-Class and
  • GetMaxim() =>Somebody set up us the bomb.

Same for an instance of Heir:

  • GetName() => Heir-Class and
  • GetMaxim() =>All your Base are belong to us!

Now I cast my instance of Heir to Base and call both functions again.

  • GetName() => Base-Class which leaves no questions and
  • GetMaxim() =>All your Base are belong to us! as expected, because it is overriden by Heir.

I added two more functions to Heir just out of curiosity.

function Heir.GetBaseName: String;
begin
  Result := inherited GetName();
end;

function Heir.GetBaseMaxim: String;
begin
  Result := inherited GetMaxim();
end;

I expect the GetBaseName() to give me Base-Class - so it happens. For GetBaseMaxim() I'm not sure. In my opinion three things are possible

  1. It doesn't compile and throws an error or
  2. It runs and will fail with an exception (because inherited function is overridden or
  3. most expected it gives me GetMaxim() from Heir telling me All your Base are belong to us!.

Neither happens! I get Somebody set up us the bomb. from my base class?! Why? I thought the function is overriden by Heir! It is not a big deal, but I don't quite understand that behavior, because it does not work as I expected. Any explanations out there?

like image 592
Stephan Avatar asked Mar 09 '16 07:03

Stephan


2 Answers

Inherited gives non-virtual dispatch to the ancestor function, and that's exactly what you observed. Most often, the function it's used from in the descendant class has the same name as the inherited function being invoked, but as you've demonstrated, that custom is not required. You can non-virtually invoke any inherited method from anywhere in the descendant class.

like image 158
Rob Kennedy Avatar answered Oct 06 '22 12:10

Rob Kennedy


This is nothing special. With inherited you request the implementation of the base class.

The documentation says:

If inherited is followed by the name of a member, it represents a normal method call or reference to a property or field, except that the search for the referenced member begins with the immediate ancestor of the enclosing method's class

like image 36
ventiseis Avatar answered Oct 06 '22 14:10

ventiseis