17

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

我有以下课程:

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

这很简单,但现在我决定创建多种自行车,每辆自行车都有自己的轮子——它们的作用与普通的前轮/后轮相同,加上特定于该自行车的轮子。

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

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

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

  1. 感觉像个黑客
  2. 强迫我多次重写相同的代码
4

10 回答 10

19

Delphi 不支持多重继承。但是类可以支持/实现多个接口,你可以委托接口实现,所以你可以模拟多重继承。

于 2009-08-14T05:37:09.793 回答
17

使用接口。像这样的东西(根据你的描述,我的头顶上......)

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++)库中的相应类所做的接口实现类,并在相应类的构造函数中实例化它们。

于 2009-08-14T06:08:41.727 回答
8

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

  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;
于 2009-08-14T10:00:54.253 回答
5

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;
于 2009-08-14T10:54:41.853 回答
4

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

所以离开这个困境,问题是:你能不能重构那个库,让你可以摆脱使用接口的方式?多重继承主要是关于函数和方法吗?如果是这样 - 使用接口。Delphi 可以在一个类上支持多个接口。

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

对不起,我不能提供一个简单的答案——这就是它的现实。

马克

于 2009-08-14T05:21:19.810 回答
3

您可以尝试从 TBikeWheelFront 中提取一个接口,例如 IFrontWheel,使其成为 TBikeWheel 的子类,但实现了 IFrontWheel。然后 TBikeWheelXYZ 继承自 TBikeWheel 和 TBikeWheelFrontXYZ 继承自 TBikeWheelXYZ 并实现 IFrontWheel。

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

这样你就没有双重实现。

于 2009-08-14T05:58:08.643 回答
2

较新版本的 Delphi 的另一种选择是在组合模型中利用泛型。TBarA这在多个基类(TBarB在此示例中)不可访问以进行修改(即:框架或库类)的情况下特别有用。例如(注意,为简洁起见,此处省略了必要destructor的 in ):TFoo<T>

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.
于 2014-08-06T12:36:23.320 回答
1

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

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;
于 2014-08-06T16:29:46.857 回答
0

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

于 2015-03-20T13:27:32.483 回答
0

我想建议以下步骤:

  1. TBikeWheelFrontXYZTBikeWheelXYZor继承类TBikeWheelFront(因为在 Delphi 中多重继承是不可能的,如上面的答案中所述)。

  2. 转换其中一个父类TBikeWheelXYZTBikeWheelFront类的类助手TBikeWheel

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

于 2021-03-01T09:13:06.503 回答