delphiinterfaceimplementationdelegation

Clarity in classes implementing multiple interfaces (alternative to delegation):


Let's say we've got the following:

IFirst = Interface(IUnknown)    
  function GetStuff: Integer;
end;
    
ISecond = Interface(IUnknown)
  function GetOtherStuff: Integer;
end;
    
TFirstSecond = class(TInterfacedObject, IFirst, ISecond)    
private 
  function GetStuff: Integer;        //implementation of IFirst
  function GetOtherStuff: Integer;   //implementation of ISecond;
end;

I have never liked the fact that in TInterfacedObject there seems to be no way to distinguish between which methods implement which interfaces. Am I missing something? Does anyone know a way structure the code to do that? To designate that GetStuff is the implementation of IFirst and GetOtherStuff is the implementation of ISecond? ('Put a comment' is not the answer I'm looking for...)

I know I can use the 'implements' directive to define properties in TFirstSecond for each interface and delegate the implementations to instances contained within TFirstSecond, thereby segregating everything. But I'd like a shortcut...


Solution

  • In the case you post, I prefer comments (interface name just as NGLN puts it) too, but I would like to explain why the implements keyword can be the best solution in some other cases, just not in trivial cases where there's only one method per interface as in your trivial sample.

    I know you said you know about Implements; but for people coming along who have not seen it, I'd like to document when it IS useful, bear with me. It is even worthwhile having all the extra work of having more classes, in some cases.

    So I would use implements not as a shortcut (as you see it's longer!) but only when each interface involves 100 methods to be implemented, and where the resulting design has less coupling, and better cohesion and readability only.

    So this is an admittedly silly example, but if each of IFirst and ISecond had 100 methods, then it might be a great leap forward...

    type
    IFirst = interface
      function GetStuff: Integer;
    end;
    
    ISecond = interface
      function GetOtherStuff: Integer;
    end;
    
    TFirstLogic = class(TInterfacedObject, IFirst)
      function GetStuff: Integer;
    
    end;
    
    TSecondLogic = class(TInterfacedObject, ISecond)
      function GetOtherStuff: Integer;
    end;
    
    TFirstSecond = class(TInterfacedObject, IFirst, ISecond)
    private
      FFirst:TFirstLogic;
      FSecond:TSecondLogic;
    protected
    
    
      property First:TFirstLogic read FFirst implements IFirst;
      property Second:TSecondLogic read FSecond implements ISecond;
    public
      constructor Create; // don't forget to create and free FFirst/FSecond.
      destructor Destroy; override; // don't forget to create and free FFirst/FSecond.
    
    
    end;
    

    You could say Implements is the only way we could do "partial classes", or at least create one composite class that implements a bunch of interfaces, and have a bunch of sub-properties (which are protected or perhaps even private) used to do the "implements" delegation. If you move everything else right out of the unit that contains the aggregating class, you could have a really clean design.