我目前正在重写一个免费的教育数字电路模拟器,以增加其功能的惯性。我的问题是如何将事件分派给原始类,为它们添加预先详细说明。我有这样的事情:
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的任何后代都不同)。
任何人都可以建议一种方法吗?
答案 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
的所有地方首先都会绕过模拟类的方法。