delphicomimplements

How to inherit a Interface from foreign Interface without reimplementing the Methods


I want to create an Interfaced object that supports an Interface from somewhere else + my own functions. So, how to stack/aggregate/enhance the Interface? I guess its possible, but I cant find a snippet or demo specific for my inheritance experiment.

This solution is not quite what I want:

TImplement = Class(TInterfacedObject, IOne, ITwo)
private
  FOne: IOne;
public
  property One: IOne read FOne implements IOne;
  property Two: ITwo read FTwo implements ITwo;
end;

Current usage:

(MyInterface as IOne).Something;
(MyInterface as ITwo).SomethingElse;

Desired usage:

MyInterface.Something;
MyInterface.SomethingElse;

I tried inheriting the Interface:

ITogether = Interface(IOne)
  procedure SomeThingElse;
end:

TImplement = Class(TInterfacedObject, ITogether)
// or Class(TInterfacedObject, ITogether, IOne) => Both result in missing Implementation message on compile ... 
private
  FOne: IOne;
  function SomeThingElse;
public
  property One: IOne read FOne implements IOne;
end;

This combination says something like:

E2291 Implementation of Method x From Interface IOne missing.

Is it possible to combine the Interface in a way so that the "cast free" calls are possible?

Edit: Rob Lambden´s answer is for me the missing Information. Uwe Raabes Answer is the Correct implementation. (And probably the only one possible) So uwe wins the answer and i can only upvote Robs answer.


Solution

  • You can implement the IOne methods and forward them to the FOne interface.

    type
      IOne = interface
        ['{19F785C0-5D2E-479F-BB2C-88A00BA4C812}']
        procedure Something;
      end;
    
      ITogether = interface(IOne)
        ['{B8B7F690-DC98-41AB-A6D9-29F70330EDA5}']
        procedure SomethingElse;
      end;
    
    type
      TTogether = class(TInterfacedObject, ITogether)
      private
        FOne: IOne;
      protected
        property One: IOne read FOne;
      public
        constructor Create(AOne: IOne);
        procedure SomethingElse;
        procedure Something;
      end;
    
    constructor TTogether.Create(AOne: IOne);
    begin
      inherited Create;
      FOne := AOne;
    end;
    
    procedure TTogether.Something;
    begin
      One.Something;
    end;
    
    procedure TTogether.SomethingElse;
    begin
      { Do something else }
    end;
    

    AFAIK, there is no language construct like implements that does that for you when the implementor is an interface property.

    Update: In case you have several cases where you need to extend the IOne interface, you can write a wrapper class that in turn makes a good candidate for the implements keyword.

    type
      TOneWrapper = class
      private
        FOne: IOne;
      protected
        property One: IOne read FOne;
      public
        constructor Create(AOne: IOne);
        procedure Something;
      end;
    
    type
      TTogether = class(TInterfacedObject, ITogether)
      private
        FOne: TOneWrapper;
      protected
        property One: TOneWrapper read FOne implements ITogether;
      public
        constructor Create(AOne: IOne);
        destructor Destroy; override;
        procedure SomethingElse;
      end;
    
    constructor TTogether.Create(AOne: IOne);
    begin
      inherited Create;
      FOne := TOneWrapper.Create(AOne);
    end;
    
    destructor TTogether.Destroy;
    begin
      FOne.Free;
      inherited Destroy;
    end;
    
    procedure TTogether.SomethingElse;
    begin
      { Do something else }
    end;
    
    constructor TOneWrapper.Create(AOne: IOne);
    begin
      inherited Create;
      FOne := AOne;
    end;
    
    procedure TOneWrapper.Something;
    begin
      One.Something;
    end;