View Issue Details

IDProjectCategoryView StatusLast Update
0036354FPCCompilerpublic2019-11-30 13:21
ReporterZamrony P. Juhara Assigned To 
Status newResolutionopen 
Product Version3.0.4 
Summary0036354: Feature request: Add ability for an interface to inherit from multiple interfaces

     IInterfaceA = interface
           procedure callA();

     IInterfaceB = interface
           procedure callB();

     IInterfaceAB = interface(IInterfaceA, IInterfaceB)

IInterfaceAB will automatically has callA() and callB() method and compatible with IInterfaceA or IInterfaceB without need to use as operator.
TagsNo tags attached.
Fixed in Revision
Attached Files


Ugochukwu Mmaduekwe

2019-11-25 08:59

reporter   ~0119483

Supported, this would be a very welcome addition.

Thaddy de Koning

2019-11-25 12:34

reporter   ~0119487

How? Are duplicate methods to be supported? (many discussions about multiple inheritance)
On class level and with as/is this is already supported. Which avoids the above.
I don't think this is a feasable option. It would require maintenance of a list of interfaces per interface and would introduce ambiguity.

Zamrony P. Juhara

2019-11-26 01:54

reporter   ~0119502

The purpose of feature I request is to avoid duplicate method by segregated interface but also combine them if required.

For example, sometime I only want a method to callA() only, sometime callB only, but other time I may need to call both.

procedure needCallA(a : IInterfaceA);

procedure needCallB(b : IInterfaceB);

procedure needBoth(ab : IInterfaceAB);

and example implementation

TAB= class(TInterfacedObject, IInterfaceAB)
     procedure callA();
     procedure callB();

var ab : IInterfaceAB;
ab := TAB.create();

In Free Pascal 3.0.4, if I need to be able to call both method and still using segregated interface

procedure needBoth(a : IInterfaceA; b : IInterfaceB);

even though underlying implementation may be coming from same class

var a: IInterfaceA;
      b : IInterfaceB;

a := TAB.create();
b := a as IInterfaceB;
needBoth(a, b);

so more variable to handle. I can create IInterfaceAB extends from IInterfaceA, but then I need to duplicate callB() method signature code

IInterfaceAB = interface(IInterfaceA)
     procedure callB();

I know its hard but it is not impossible. Java, C#, Go, PHP, they allow an interface to extends from one or more interfaces.

Thaddy de Koning

2019-11-26 08:32

reporter   ~0119504

It is not quite the same, but there is support to extend an existing interface through type helpers from 3.2.0
And in trunk, multiple helpers can be in scope at the same time:

This can be used to achieve the same effect (and has the same drawbacks as e.g. in Java)

Thaddy de Koning

2019-11-26 12:24

reporter   ~0119505

See also

Zamrony P. Juhara

2019-11-27 02:26

reporter   ~0119522

I am aware of diamond problem when dealing with class multiple inheritance. But feature I request is not about a class inherit from multiple classes. CMIIW, interface extends from multiple interfaces does not have diamond problem because an interface only defines method signature not how it should be implemented. So if multiple interfaces shares indentical method signature, descendant interface can merge them as one.

Marco van de Voort

2019-11-29 11:47

manager   ~0119549

Last edited: 2019-11-29 11:51

View 3 revisions

I thought about it, but the trick will be how to get the sub interface. IOW if objectA implements the both interface, how do I get a reference for only the A or B interface?

With single inheritance ancestors still start at the first item, just the length varies. With this construct, also an offset is needed since one of the two will be at an offset of A. Maybe importing into object a can take care of that in the tables, maybe not, but my guess is that's where the trouble is.

Sven Barth

2019-11-30 13:21

manager   ~0119560

There is also the following to consider:

=== code begin ===

  IInterfaceA = interface
    procedure callA;

  IInterfaceB = interface
    procedure callB;

  IInterfaceAB = interface({IInterfaceA, }IInterfaceB)

  TMyClass = class(TInterfacedObject, IInterfaceAB, IInterfaceA)
    procedure IInterfaceA.callA = myCallA;
    procedure myCallA;
    procedure callB;

=== code end ===

Now do I need to have to declare callA nevertheless, because IInterfaceAB requires it? Or do I have to alias IInterfaceAB.callA as well? (I'd say the later, cause that is then consistent with how inherited interfaces behave currently)

And the point that Marco mentioned is important as well: you can only get directly implemented interfaces through GetInterface, this is not going to change, because that opens a whole other can of worms. If you only implement IInterfaceAB then you *can not* get a direct reference to an IInterfaceA without first retrieving the IInterfaceAB and then converting that to an IInterfaceA. And there we'll then have the problem of correctly constructing the method tables: We'll essentially have to copy the way vtables work in MSVC, because the whole concept of interfaces is supposed to be COM compatible which is essentially MS Visual C++.

Issue History

Date Modified Username Field Change
2019-11-25 06:40 Zamrony P. Juhara New Issue
2019-11-25 08:59 Ugochukwu Mmaduekwe Note Added: 0119483
2019-11-25 12:34 Thaddy de Koning Note Added: 0119487
2019-11-26 01:54 Zamrony P. Juhara Note Added: 0119502
2019-11-26 08:32 Thaddy de Koning Note Added: 0119504
2019-11-26 12:24 Thaddy de Koning Note Added: 0119505
2019-11-27 02:26 Zamrony P. Juhara Note Added: 0119522
2019-11-29 11:47 Marco van de Voort Note Added: 0119549
2019-11-29 11:48 Marco van de Voort Note Edited: 0119549 View Revisions
2019-11-29 11:51 Marco van de Voort Note Edited: 0119549 View Revisions
2019-11-30 13:21 Sven Barth Note Added: 0119560