[fpc-pascal] Inherit interface from 2 interfaces

Andreas Dorn adornno1 at web.de
Tue Apr 12 23:46:32 CEST 2011


On Tue Apr 12, michael.vancanneyt worte:
> On Tue, 12 Apr 2011, Andreas Dorn wrote:
>> On Fri, 8 Apr 2011, michael.vancanneyt worte:
>>> The whole idea of interfaces is to avoid multiple inheritance.
>>>
>> Hm. I don't believe that.
>>
>> One of the major points of interfaces is indeed to avoid the problems
>> of multiple class inheritance (diamond problems - i.e. problems caused by
>> conflicting implementations of a method in different ancestor classes).
>>
>> But Interfaces themselves don't have an implementation, so those
>> diamond problems simply don't exist for them.
>
> Of course they do. If they inherit from 2 interfaces that have the same
> method with a different signature, you have a problem.
>
> InterfaceA = Interface
>    Function IsValid : Integer;
> end;
>
> InterfaceB = Interface
>    Function IsValid : String;
> end;

Good point.

Well, I don't see a diamond here as such a serious problem as it is
for multiple class inheritance. (where eventually trying to override
the conflicting methods in descendant classes will bite...)

C# handles multiple interface inheritance quite well, so I'm quite
confident that it's possible to get it done right.

As far as I've seen the "diamond problem for interface inheritance"
there just means that it's not directly possible to call an
ambigous method directly from InterfaceC without first casting to
Interface A or B - and that sounds rational to me. What's important is
that you can get from C to A and B without a blind cast and then call
the method you like.

> How to define :
>
> InterfaceC = Interface(InterfaceA,InterfaceB)

Let's give it a try:

Interface A and B are sets of pointers to Methods, InterfaceC then
simply is the union of those sets. (As a pure contract InterfaceC
itself doesn't really have to contain non-ambiguous signatures)

It's no problem for a class to implement Interface A and B at
the same time anyway...

TTest = class(TObject, InterfaceA, InterfaceB)
   function InterfaceA.IsValid = IsValid_A;
   function InterfaceB.IsValid = IsValid_B;

   function IsValid_A: Integer;
   function IsValid_B: String;
end;

All ambiguities regarding implementation can be resolved by the 
implementing class. It just has to map all the pointers to 
(non-conflicting) method implementations.

..

Finally I'd like to mention one usecases for interface inheritance I'd 
like to have:
1) Splitting a big IDataInterface into smaller ones, like:
IDataInterface = Interface(IInitMethods, IReadMethods, IEditMethods, ...)

This would allow me to pass an IDataInterface into Factories, Loggers, 
etc. without passing too many methods and without ugly runtime casts
or artificial single-inheritance chains...

2) Containers. Without multiple inheritance it's a pain to get
some things like:
IMyContainer = Interface(ISortableContainer, IVectorList, IEditableList, 
...)

Practically for me not having multiple interface inheritance sometimes 
leads to:
  a) artificial (single) inheritance chains
  b) blind runtime casts instead of casts to a known parent
  c) having to pass parameters that are bigger than necessary
     (IQuery instead of IReadOnlyQuery)

All in all I'd really like to have multiple interface inheritance...

-- 
Andreas.




More information about the fpc-pascal mailing list