delphi中如何实现多重继承?

发布于 2024-08-02 01:47:05 字数 745 浏览 2 评论 0原文

我正在对一个旧库进行完全重写,我不确定如何处理这种情况(为了便于理解,大家都欢呼自行车类比):

我有以下类:

  • TBike - 自行车本身
  • TBikeWheel - 自行车车轮之一
  • TBikeWheelFrontTBikeWheelBack,两者都继承自 TBikeWheel 和然后在其之上实现他们需要的特定内容

这非常简单,但现在我决定创建多种自行车,每辆自行车都有自己的车轮 - 它们与常规前轮/后轮执行相同的操作,加上那辆自行车的具体情况。

  • TBikeXYZ - 继承自 TBike
  • TBikeWheelXYZ - 继承于 TBikeWheel

这是我的问题:TBikeWheelFrontXYZ code> 应该继承自 TBikeWheelXYZ (获取 XYZ 轮的具体方法),但它也应该继承自 TBikeWheelFront (获取前轮的具体方法) 。

我的问题是,我怎样才能以一种不这样的方式实现它:

  1. 感觉就像黑客
  2. 迫使我多次重写相同的代码

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

漆黑的白昼 2024-08-09 01:47:06

我想建议以下步骤:

  1. TBikeWheelXYZTBikeWheelFront 继承 TBikeWheelFrontXYZ 类(因为在 Delphi 中多重继承是不可能的)正如上面的答案中提到的)。

  2. 将父类 TBikeWheelXYZTBikeWheelFront 之一转换为 TBikeWheel 类的类帮助器。

  3. 将类帮助器单元添加到声明 TBikeWheelFrontXYZ 类的单元中。

I would like to suggest the following steps:

  1. Inherit the TBikeWheelFrontXYZ class from either TBikeWheelXYZ or TBikeWheelFront (since in Delphi multiple inheritance is impossible as mentioned in the answers above).

  2. Convert one of the parent classes TBikeWheelXYZ or TBikeWheelFront to class helper for the TBikeWheel class.

  3. Add the class helper unit to the unit, where the TBikeWheelFrontXYZ class is declared.

⒈起吃苦の倖褔 2024-08-09 01:47:05

Delphi 不支持多重继承。 但是类可以支持/实现多个接口,并且您可以委托接口实现,因此您可以模拟多重继承。

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.

伴我心暖 2024-08-09 01:47:05

使用接口。 像这样的东西(根据你的描述,在我的脑海中......)

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);

然后为接口实现类,这些类执行旧(大概是 C/C++)库中相应类的操作,并在相应的库中实例化它们类的构造函数。

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.

沫离伤花 2024-08-09 01:47:05

使用多态性将每个“事物”实现为一个对象层次结构,然后依次向该对象添加对象属性。 因此,创建车轮层次结构和自行车层次结构。 然后将车轮添加到自行车作为祖先自行车对象中的字段。 见下文。

  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;

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;
云归处 2024-08-09 01:47:05

Brian Frost 建议的变体:

  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;

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;
睫毛上残留的泪 2024-08-09 01:47:05

基本上 - 你不能。 Delphi 不支持多重继承。

因此,留下这样的困境,问题是:你是否可以重构该库,以便你可以摆脱使用接口的束缚? 多重继承主要是关于函数和方法吗? 如果是这样 - 使用接口。 Delphi 可以支持一个类上的多个接口。

如果多重继承更多的是继承类中的实际功能,那么恐怕您可能会考虑更大规模的重构。 您需要找到一种方法来分解这些功能依赖关系,这样您就可以使其继承自单个基类,可能还需要添加一些附加接口。

抱歉,我无法提供一个简单的答案 - 这只是它的现实。

马克

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

素衣风尘叹 2024-08-09 01:47:05

您可以尝试从 TBikeWheelFront 中提取一个接口,例如 IFrontWheel,这样它就是 TBikeWheel 的子类,但实现了 IFrontWheel。 然后TBikeWheelXYZ继承自TBikeWheel,TBikeWheelFrontXYZ继承自TBikeWheelXYZ并实现IFrontWheel。

然后,您可以定义一个类 TFrontwheel 并为其提供与接口相同的方法,但现在您可以实现它们。 然后 TBikeWheelFront 和 TBikeWheelXYZ 获得类型 TFrontwheel 的私有成员,并且它们的 IFrontWheel 实现简单地委托给私有成员方法。

这样你就不会有双重实现。

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.

べ繥欢鉨o。 2024-08-09 01:47:05

新版本 Delphi 的另一种选择是在组合模型中利用泛型。 这在多个基类(本例中的TBarATBarB)不可访问修改(即:框架或库类)的情况下特别有用。 例如(请注意,为简洁起见,此处省略了 TFoo 中必要的析构函数):

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.

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.
才能让你更想念 2024-08-09 01:47:05

如果您不想多次重复代码并且想要解耦代码,您可以尝试这种方式。

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;

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;
九命猫 2024-08-09 01:47:05

抱歉,Delphi 不支持多重继承。

Sorry, Delphi does not support Multiple Inheritance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文