Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2025-04

Overridden method with different signature - compiles - should it?

3 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Martin Frb

See the below code. (tested 3.2.3 and 3.3.1)

Is this intentionally allowed?

Technically it should work. TSubTest.Test always returns something that fits the inherited requirement.

program Project1;
type
   TFoo = class end;
   TBar = class(TFoo) end;
   TTest = class
     function Test: TFoo; virtual; abstract;
   end;
   TSubTest = class(TTest)
     function Test: TBar; override;
   end;
function TSubTest.Test: TBar;
begin  end;

begin  end.

And if that is intentional, then why not also

   TTest = class
     procedure Test(a: TBar); virtual; abstract;
   end;
   TSubTest = class(TTest)
     procedure Test(a: TFoo); override;
   end;

This fails. Even though any TBar passed will be fine to the base and the subclass.

And any
  var sub: TSubTest
will accept TFoo too, but such a var can never hold the base class.

Reply by email

Sven Barth
to Martin Frb

Martin Frb via fpc-devel schrieb am Sa.,
5. Apr. 2025, 12:02:

Show quoted text 26 lines
See the below code. (tested 3.2.3 and 3.3.1) Is this intentionally allowed? Technically it should work. TSubTest.Test always returns something that fits the inherited requirement. program Project1; type TFoo = class end; TBar = class(TFoo) end; TTest = class function Test: TFoo; virtual; abstract; end; TSubTest = class(TTest) function Test: TBar; override; end; function TSubTest.Test: TBar; begin end; begin end.

Yes, this is intentional and is called "covariant return type" ( https://en.m.wikipedia.org/wiki/Covariant_return_type ).

Show quoted text 18 lines
And if that is intentional, then why not also TTest = class procedure Test(a: TBar); virtual; abstract; end; TSubTest = class(TTest) procedure Test(a: TFoo); override; end; This fails. Even though any TBar passed will be fine to the base and the subclass. And any var sub: TSubTest will accept TFoo too, but such a var can never hold the base class.

This is called contra-variance and is in general not something that programming languages support. See for example here: https://stackoverflow.com/questions/2995926/why-is-there-no-parameter-contra-variance-for-overriding

Regards,
Sven

Reply by email