如何将不同的类封装在一个类中并保持其独特的方法? (delphi中的多重继承?)

发布于 2024-08-23 15:27:33 字数 1212 浏览 3 评论 0原文

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

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

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

任何人都可以建议一种方法来做到这一点?

I'm currently rewriting a free educational digital circuit simulator to add inertiality to its features. My problem is how to dispatch events to original classes adding a pre-elaboration to them. I have something like this:

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;

Now this means that ContFunc call C2.Func1 as I wish, specializing behaviour of more than 300 components inheriting form TC1.

But now I have to add some special operations (equal for all component descendants
from TC1 every time Func1 is called, and chosing during that operations if I have to
call TC2-n.Func1 or not (after changing some property of ancestor TC1.
Is there a way to do that cleanly, without changing all descendants of TC1?
Can I use a helper class (deprecated?) like this:

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

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

If I add TH, when TContainer call Func1, who is called?
It call TC2.Func1 and not TH.Func1 as I wished?.
Is there a way to override descenants method Func1
without writing an helper class for any single one (they will do all
the same operations, meaning exactly equal code)?
It is possible to call from TH the 300 descendant functions Func1 of TC2-n ?

In other words, I'm trying to find a way to obtain a call like this by Tcontainer call to c1.Func1;:

NewFunc1 (equal for all TC1 descendants) who call TC2.Func1 (different for any descendant of TC1).

Anyone can suggest a way to do that?

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

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

发布评论

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

评论(3

合久必婚 2024-08-30 15:27:33

每当有人调用 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 的重构工具也许能够帮助解决这个问题。

You have some tasks that need to be performed whenever someone calls Func1, regardless of what descendants have chosen to do in their overridden methods. This is a job for the template method pattern.

Give the base class a public non-virtual method Func1 that performs the operations you need and then invokes a protected virtual method. The descendants can override that virtual method, but anyone using the class can only call the public non-virtual method.

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;

Now descendants can override InternalFunc1, and the base class will make sure it gets called only when appropriate.

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

You'll need to rename your current Func1 function in all your 300 descendant classes. The IDE's refactoring tools might be able to help with that.

二货你真萌 2024-08-30 15:27:33

类助手对于修改您无法从源代码获取的类非常有用。如果您是 TC1 类的作者,并且您能够通过引入 TC1 的类帮助器来进行必要的更改,那么为什么不直接修改 TC1.Func1,然后就完成了呢?那应该有效。

Class helpers are useful for modifying classes you can't get at the source to. If you're the author of class TC1, and you would be able to make the necessary changes by introducing a class helper for TC1, then why not just modify TC1.Func1, and then you're done? That should work.

拥抱影子 2024-08-30 15:27:33

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

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 的所有位置都会首先绕道到模拟类的方法。

You can make a wrapper class following the decorator pattern to describe the special tasks that need to occur when your program is operating in analogue mode. It can hold an instance of your digital component and call that component's methods after performing its own tasks.

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;

Notice how there's no need to check your x condition beforehand. Instead of checking it each time you call any method, you can check it once before wrapping the digital component with the analogue one. Now all the places where you originally called Func1 directly on the digital class get detoured to the analogue class's methods first.

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