如何在一个类中封装不同的类来维护它们的独特方法? (在delphi中多重继承?)

时间:2010-03-02 11:49:32

标签: delphi multiple-inheritance class-helpers

我目前正在重写一个免费的教育数字电路模拟器,以增加其功能的惯性。我的问题是如何将事件分派给原始类,为它们添加预先详细说明。我有这样的事情:

TC1 = class
  ID: integer;
  Connections : array [integer] of Pin;
  function Func1; virtual;
  function FuncN;
end;

TC2-1 = class (TC1)
  function Func1; override;
  function My1Func();
end;

TC2-n = class (TC1)
  function Func1; override;
  function MyNFunc();
end;


TContainer = class
  C1 : TC1;
  function ContFunc;
end;

function Container.ContFunc;
begin
    c1.Func1;
end;

现在这意味着ContFunc会根据需要调用C2.Func1,专门处理从TC1继承的300多个组件的行为。

但现在我必须添加一些特殊操作(对所有组件后代都相同) 每次调用Func1时从TC1开始,如果必须的话,在操作期间选择 是否调用TC2-n.Func1(更改祖先TC1的某些属性后)。 有没有办法干净地做到这一点,而不改变TC1的所有后代? 我可以使用这样的辅助类(不建议使用?):

TH = class helper of TC1
  function Func1 virtual; override;
end;

function TH.Func1;
begin
  if x then TC2.Func1 else SaveActionData; 
end

如果我添加TH,当TContainer调用Func1时,谁被调用? 它按我的意愿调用TC2.Func1而不是TH.Func1。 有没有办法覆盖下降方法Func1 没有为任何一个人写一个助手类(他们会做所有 相同的操作,意味着完全相同的代码)? 可以从TH调用TC2-n的300个后代函数Func1

换句话说,我正在尝试通过Tcontainer调用c1.Func1来找到一种方法来获取这样的调用;:

调用TC2.Func1的NewFunc1(对于所有TC1后代都相同)(对于TC1的任何后代都不同)。

任何人都可以建议一种方法吗?

3 个答案:

答案 0 :(得分:4)

每当有人调用Func1时,您都需要执行一些任务,无论后代在其重写方法中选择做什么。这是模板方法模式的工作。

为基类提供一个公共非虚方法Func1,它执行您需要的操作,然后调用受保护的虚方法。后代可以覆盖该虚方法,但使用该类的任何人只能调用公共非虚方法。

type
  TC1 = class
  protected
    function InternalFunc1: Integer; virtual; // abstract?
  public
    function Func1: Integer;
  end;

function TC1.Func1;
begin
  if x then
    Result := InternalFunc1
  else
    Result := SaveActionData; 
end;

现在后代可以覆盖InternalFunc1,基类将确保仅在适当时调用它。

type
  TC2 = class(TC1)
  protected
    function InternalFunc1: Integer; override;
  end;

您需要在所有300个后代类中重命名当前的Func1函数。 IDE的重构工具可能能够帮助解决这个问题。

答案 1 :(得分:0)

类助手可用于修改源无法获取的类。如果您是TC1类的作者,并且您可以通过为TC1引入类助手来进行必要的更改,那么为什么不修改TC1.Func1,然后您就完成了?这应该有用。

答案 2 :(得分:0)

您可以按照装饰器模式创建一个包装类,以描述当您的程序在模拟模式下运行时需要执行的特殊任务。它可以保存数字组件的实例,并在执行自己的任务后调用该组件的方法。

type
  TAnalogueDecorator = class(TC1)
  private
    FComponent: TC1;
  public
    constructor Create(Wrapped: TC1);
    destructor Destroy; override;

    function Func1: Integer; override;
  end;

constructor TAnalogueDecorator.Create(Wrapped: TC1);
begin
  inherited Create;
  FComponent := Wrapped;
end;

destructor TAnalogueDecorator.Destroy;
begin
  FComponent.Free;
  inherited;
end;

function TAnalogueDecorator.Func1: Integer;
begin
  SaveActionData;
  Result := FComponent.Func1;
end;

请注意,无需事先检查x条件。每次调用任何方法时都可以检查它,而不是在用数字组件包装数字组件之前检查一次。现在,你最初在数字类上直接调用Func1的所有地方首先都会绕过模拟类的方法。