How to implement multiple inheritance in delphi?

倖福魔咒の 提交于 2019-11-26 16:54:56

问题


I'm doing a full rewrite of an old library, and I'm not sure how to handle this situation (for the sake of being understood, all hail the bike analogy):

I have the following classes:

  • TBike - the bike itself
  • TBikeWheel - one of the bike's wheel
  • TBikeWheelFront and TBikeWheelBack, both inherits from TBikeWheel and then implements the specific stuff they need on top of it

This is pretty straightforward, but now I decide to create multiple kind of bikes, each bikes having it's own kinds of wheel - they do the same stuff as a regular front/back wheels, plus the specific for that bike.

  • TBikeXYZ - inherits from TBike
  • TBikeWheelXYZ - inherits from TBikeWheel

And here is my problem: TBikeWheelFrontXYZ should inherit from TBikeWheelXYZ (to get the specific methods of an XYZ wheel), but it should also inherit from TBikeWheelFront (to get the specific methods of a front wheel).

My question here is, how can I implement that in a way that doesn't:

  1. feel like a hack
  2. force me to rewrite the same code several time

回答1:


Delphi does not support Multiple Inheritance. But classes can support / implement multiple interfaces and you can delegate interface implementation, so you can kinda simulate multiple inheritence.




回答2:


Use interfaces. Something like this (Off the top of my head, based on your description.....)

type

  IBikeWheel = interface
    ...
  end;

  IXYZ = interface
    ...
  end;

  IFrontWheel = interface(IBikeWheel)
    ...
  end;


  TBike = class
    ...
  end;

  TBikeWheel = class(TObject, IBikeWheel);

  TBikeWheelXYZ = class(TBikeWheel, IXYZ);

  TBikeFrontWheelXYZ = class(TBikeWheelXYZ, IFrontWheel);

Then implement classes for the interfaces that do what the corresponding classes in your old (presumably C/C++) library does and instantiate them in the corresponding class's constructor.




回答3:


Use polymorhism to implment each 'thing' as an object hierarchy in its own right and then add object properties to that object in turn. So, create a hierarchy of wheels, and a hierarchy of bikes. Then add wheels to bikes as fields in the ancestor bike object. See below.

  TBikeWheel = class
  TBikeWheelXYZ = class( TBikeWheel ) 

  TBike = class
    FFrontWheel : TBikeWheel;
    property FrontWheel : TBikeWheel
      read FrontWhell  

  TBikeABC = class( TBike)
    constructor Create;
  end;

  constructor TBikeABC.Create;
  begin
    inherited;
    FFrontWheel := TBikeWheel.Create;
  end;

  TBikeXYZ = class( TBike)
    constructor Create;
  end;

  constructor TBikeXYZ.Create;
  begin
    inherited;
    FFrontWheel := TBikeWheelXYZ.Create;
  end;



回答4:


A variation of Brian Frost's suggestion:

  TBikeWheel = class
  TBikeWheelXYZ = class( TBikeWheel ) 

  TBike = class
    FFrontWheel : TBikeWheel;
  protected
    function CreateWheel: TBikeWheel; virtual;
  public
    property FrontWheel : TBikeWheel
      read FrontWheel  
  end;

  TBikeABC = class( TBike)
  protected
    function CreateWheel: TBikeWheel; override;
  end;

  function TBikeABC.CreateWheel: TBikeWheel;
  begin
    result := TBikeWheel.Create;
  end;

  TBikeXYZ = class( TBike)
  protected
    function CreateWheel: TBikeWheel; override;
  end;

  function TBikeXYZ.CreateWheel: TBikeWheel;
  begin
    result := TBikeWheelXYZ.Create;
  end;



回答5:


Basically - you CAN'T. Delphi does not support multiple inheritance.

So left with that dilemma, the question is: could you possibly refactor that library in such a way that you can get away with using interface? Is the multiple inheritance mostly about functions and methods? If so - use interfaces. Delphi can support multiple interfaces on a class.

If the multi-inheritance is more about inheriting actual functionality in the classes, then you're probably looking at a bigger scale refactoring, I'm afraid. You'll need to find a way to break up those functional dependencies in such a way you can make it inherit from a single base class, possibly with some additional interfaces thrown in.

Sorry I can't provide an easy answer - that's just the reality of it.

Marc




回答6:


You can try to extract an interface, say IFrontWheel, out of TBikeWheelFront, so that it is a subclass of TBikeWheel but implements IFrontWheel. Then TBikeWheelXYZ inherits from TBikeWheel and TBikeWheelFrontXYZ inherits from TBikeWheelXYZ and implements IFrontWheel.

Then you can define a class TFrontwheel and give it the same methods as the interface, but now you implement them. Then TBikeWheelFront and TBikeWheelXYZ get a private member of type TFrontwheel and the IFrontWheel implementations of them simply delegate to the private member methods.

This way you don't have double implementations.




回答7:


Another alternative with newer versions of Delphi is to leverage generics in a compositional model. This is particularly useful in the case where the multiple base classes (TBarA and TBarB in this example) are not accessible for modification (ie: framework or library classes). For example (note, the necessary destructor in TFoo<T> is omitted here for brevity) :

program Project1;

uses SysUtils;

{$APPTYPE CONSOLE}

type    
  TFooAncestor  = class
    procedure HiThere; virtual; abstract;
  end;
  TBarA = class(TFooAncestor)
    procedure HiThere; override;
  end;
  TBarB = class(TFooAncestor)
    procedure HiThere; override;
  end;
  TFoo<T: TFooAncestor, constructor> = class
    private
      FFooAncestor: T;
    public
      constructor Create;
      property SomeBar : T read FFooAncestor write FFooAncestor;
  end;

procedure TBarA.HiThere;
begin
  WriteLn('Hi from A');
end;

procedure TBarB.HiThere;
begin
  WriteLn('Hi from B');
end;

constructor TFoo<T>.Create;
begin
  inherited;
  FFooAncestor := T.Create;
end;

var
  FooA : TFoo<TBarA>;
  FooB : TFoo<TBarB>;
begin
  FooA := TFoo<TBarA>.Create;
  FooB := TFoo<TBarB>.Create;
  FooA.SomeBar.HiThere;
  FooB.SomeBar.HiThere;
  ReadLn;
end.



回答8:


you can try this way, if you do not want to repeat the code several times and want a decoupled code.

type
   TForm1 = class(TForm)
    btnTest: TButton;
    procedure btnTestClick(Sender: TObject);
   private
      { Private declarations }
   public
      { Public declarations }
   end;

   TBike = class
   end;

   IBikeWheel = interface
      procedure DoBikeWheel;
   end;

   TBikeWheel = class(TInterfacedObject, IBikeWheel)
   public
      procedure DoBikeWheel;
   end;

   IBikeWheelFront = interface
      procedure DoBikeWheelFront;
   end;

   TBikeWheelFront = class(TInterfacedObject, IBikeWheelFront)
   public
      procedure DoBikeWheelFront;
   end;

   IBikeWheelBack = interface
   end;

   TBikeWheelBack = class(TInterfacedObject, IBikeWheelBack)
   end;

   TBikeWheelFrontXYZ = class(TInterfacedObject, IBikeWheel, IBikeWheelFront)
   private
      FIBikeWheel: IBikeWheel;
      FBikeWheelFront: IBikeWheelFront;
   public
      constructor Create();
      property BikeWheel: IBikeWheel read FIBikeWheel implements IBikeWheel;
      property BikeWheelFront: IBikeWheelFront read FBikeWheelFront implements IBikeWheelFront;
   end;

var
   Form1: TForm1;

implementation

{$R *.DFM}

{ TBikeWheel }

procedure TBikeWheel.DoBikeWheel;
begin
   ShowMessage('TBikeWheel.DoBikeWheel');
end;

{ TBikeWheelFrontXYZ }

constructor TBikeWheelFrontXYZ.Create;
begin
   inherited Create;
   Self.FIBikeWheel := TBikeWheel.Create;
   Self.FBikeWheelFront := TBikeWheelFront.Create;
end;

{ TBikeWheelFront }

procedure TBikeWheelFront.DoBikeWheelFront;
begin
   ShowMessage('TBikeWheelFront.DoBikeWheelFront');
end;

procedure TForm1.btnTestClick(Sender: TObject);
var
   bikeWhell: TBikeWheelFrontXYZ;
begin
   bikeWhell := nil;
   try
      try
         bikeWhell := TBikeWheelFrontXYZ.Create;
         IBikeWheelFront(bikeWhell).DoBikeWheelFront;
         IBikeWheel(bikeWhell).DoBikeWheel;
      except
         on E: Exception do
         begin
            raise;
         end;
      end;
   finally
      if Assigned(bikeWhell) then FreeAndNil(bikeWhell);
   end;                                          
end;



回答9:


Sorry, Delphi does not support Multiple Inheritance.



来源:https://stackoverflow.com/questions/1276173/how-to-implement-multiple-inheritance-in-delphi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!