Sign in Join

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

Mailing lists / fpc-devel / 2026-02

Question on interface inheritance...

7 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

The below example throws a compile error... Technical correct, well... (doesn't matter which of the 2 intf I use as return type...)

Also, same when doing (in the 2 interfaces / yes override compiles with
inherited return type)
     function GetFoo: TIntfFooBase; virtual;
     function GetFoo: TIntfFoo; override;

TIntFoo covers all that is TintFooBase => so that should/could cover the requirement?

Is that error by indent (for which reason)?
Or by oversight?

In any case, how can it actually be added?
- Obviously I can not have 2 identical functions with just a different return type.
- I could do:
    function BaseGetFoo: TIntfFooBase;
    function TIntfBarBase.GetFoo = BaseGetFoo;

But that only compiles if I do add both interfaces:    TMyClass = class(TObject, TIntfBar, TIntfBarBase) And then I still get the error about the missing method.

Neither does this work.
     function GetFoo: TIntfFoo;
     function BaseGetFoo: TIntfFooBase;
     function TIntfBar.GetFoo = BaseGetFoo;
Which then gives (the reintroduced method is now missing / of course,
since the other is forced)
project1.lpr(24,14) Error: No matching implementation for interface
method "GetFoo:TIntfFoo;" found
and neither (same error / no error about setting the intf method twice)
   TMyClass = class(TObject, TIntfBar)
     function NewGetFoo: TIntfFoo;
     function BaseGetFoo: TIntfFooBase;
     function TIntfBar.GetFoo = NewGetFoo;
     function TIntfBar.GetFoo = BaseGetFoo;
   end;
program Project1;
{$Mode objfpc}{$Interfaces CORBA}
type
   TIntfFooBase = interface
   end;
   TIntfFoo = interface(TIntfFooBase)
   end;
   TIntfBarBase = interface
     function GetFoo: TIntfFooBase;
   end;
   TIntfBar = interface(TIntfBarBase)
     function GetFoo: TIntfFoo; reintroduce;
   end;
   // project1.lpr(21,14) Error: No matching implementation for
interface method "GetFoo:TIntfFooBase;" found
   TMyClass = class(TObject, TIntfBar)
     function GetFoo: TIntfFoo;
   end;
function TMyClass.GetFoo: TIntfFoo;
begin
   //
end;
begin
end.

Reply by email

Mattias Gaertner
to Martin Frb
Martin Frb wrote 6 lines
[...]   TIntfBarBase = interface     function GetFoo: TIntfFooBase;   end;   TIntfBar = interface(TIntfBarBase)     function GetFoo: TIntfFoo; reintroduce;

reintroduce is not allowed in Delphi and should not in fpc neither.

Mattias

Reply by email

Martin Frb
to Mattias Gaertner
Mattias Gaertner wrote 11 lines
On 2/1/26 15:29, Martin Frb via fpc-devel wrote: > [...] >    TIntfBarBase = interface >      function GetFoo: TIntfFooBase; >    end; >    TIntfBar = interface(TIntfBarBase) >      function GetFoo: TIntfFoo; reintroduce; reintroduce is not allowed in Delphi and should not in fpc neither.

It compiles without reintroduce too (just has a warning).

Or do you mean, the act of reintroduction, rather than the keyword?

----
What surprised me more was that virtual/override compiled => but it seems its just ignored, as it gives a warning as if it wasn't there.

Reply by email

Martin Frb
to Martin Frb

Background is that I then wanted (in my case via a generic) wanted code that can perform actions on the base-interface.

But would be specialized with the concrete interface, so if an instance of the interface (the one retrieved as result) is passed around, it as the more specific class.

Otherwise, I have to write the generic without type constraints....

Reply by email

Mattias Gaertner
to Martin Frb: It compiles without reintroduce too (just has a warning). Or do you mean, the act of…
Martin Frb wrote 16 lines
On 01/02/2026 15:44, Mattias Gaertner via fpc-devel wrote: > > > On 2/1/26 15:29, Martin Frb via fpc-devel wrote: >> [...] >>    TIntfBarBase = interface >>      function GetFoo: TIntfFooBase; >>    end; >>    TIntfBar = interface(TIntfBarBase) >>      function GetFoo: TIntfFoo; reintroduce; > > reintroduce is not allowed in Delphi and should not in fpc neither. It compiles without reintroduce too (just has a warning). Or do you mean, the act of reintroduction, rather than the keyword?

I think the compiler should not allow reintroducing in interfaces.

In Delphi you get the same problem, stopping with

TIntfBarBase.GetFoo is not implemented

Mattias

Reply by email

Martin Frb
to Mattias Gaertner
Mattias Gaertner wrote 11 lines
On 2/1/26 15:51, Martin Frb via fpc-devel wrote: > > Or do you mean, the act of reintroduction, rather than the keyword? I think the compiler should not allow reintroducing in interfaces. In Delphi you get the same problem, stopping with TIntfBarBase.GetFoo is not implemented

Ok, lets see what other think / it wont help for now either, since it wont work with the current compiler.

But I do think that (other than the work for the compiler devs) it would be a neat feature.

Though, probably only if the reintroduced version returns a subclass of the original

IFaceBase
    GetFoo: TFooBase;
IFace(IFaceBase)
    GetFoo: TFoo;

Since TFoo inherits from TFooBase the new interface still 100% fulfils the contract of the base.

Technically the interfaces still work even if the types are non compatible (since the method of the base interface still exists in the inherited, it only can't be accessed directly)

Reply by email

Martin Frb
to Martin Frb
Martin Frb wrote 7 lines
Ok, lets see what other think / it wont help for now either, since it wont work with the current compiler. But I do think that (other than the work for the compiler devs) it would be a neat feature.

And as I said it comes in useful if you have a generic...

I wanted

interface BaseList
  function IntfBaseItem

interface FooList(BaseList)
  function IntfFooItem  (inherits BaseItem)

generic ListFeature<_LIST: BaseList, _ITEM: BaseItem> = class
   procedure DoSomething(AnItem: _Item); virtual;
   procedure DoWork....;
end;

DoWork would go over the list, and for the correct items call DoSomething.

DoSomeThing needs the correct class, so if I specialize this as base, my new class

type TBar = class(specialize ListFeature<FooList, FooItem>)
   procedure DoSomething(AnItem: FooItem); override;
end

can access all the stuff that FooItem has.

Reply by email