如何用 2 个或更多类实现相同的方法?

发布于 2024-12-26 03:00:22 字数 1287 浏览 0 评论 0原文

我想编写一个具有 3 个相同方法的 TCheckBoxTRadioButton 后代。

TMyCheckBox = class(TCheckBox)
  procedure DoSomething1;
  procedure DoSomething2;
  procedure WMSize(var Message: TWMSize); message WM_SIZE;
end;

TMyRadioButton = class(TRadioButton)
  procedure DoSomething1;
  procedure DoSomething2;
  procedure WMSize(var Message: TWMSize); message WM_SIZE;
end;

// the following procedures are common for both classes, so in fact
// TMyCheckBox.DoSomething1 do the same as TMyRadioButton.DoSomething1

procedure DoSomething1;
begin
  // here is the same code for TMyCheckBox as well as for TMyRadioButton
  // but I don't want to write the same code many times but implement it
  // for both classes at once in some common way
end;

procedure DoSomething2;
begin
  // here is the same code for TMyCheckBox as well as for TMyRadioButton
  // but I don't want to write the same code many times but implement it
  // for both classes at once in some common way
end;

procedure WMSize(var Message: TWMSize); message WM_SIZE;
begin
  // here is the same code for TMyCheckBox as well as for TMyRadioButton
  // but I don't want to write the same code many times but implement it
  // for both classes at once in some common way
end;

我该怎么做?

I want to write a TCheckBox and TRadioButton descendants having 3 identical methods.

TMyCheckBox = class(TCheckBox)
  procedure DoSomething1;
  procedure DoSomething2;
  procedure WMSize(var Message: TWMSize); message WM_SIZE;
end;

TMyRadioButton = class(TRadioButton)
  procedure DoSomething1;
  procedure DoSomething2;
  procedure WMSize(var Message: TWMSize); message WM_SIZE;
end;

// the following procedures are common for both classes, so in fact
// TMyCheckBox.DoSomething1 do the same as TMyRadioButton.DoSomething1

procedure DoSomething1;
begin
  // here is the same code for TMyCheckBox as well as for TMyRadioButton
  // but I don't want to write the same code many times but implement it
  // for both classes at once in some common way
end;

procedure DoSomething2;
begin
  // here is the same code for TMyCheckBox as well as for TMyRadioButton
  // but I don't want to write the same code many times but implement it
  // for both classes at once in some common way
end;

procedure WMSize(var Message: TWMSize); message WM_SIZE;
begin
  // here is the same code for TMyCheckBox as well as for TMyRadioButton
  // but I don't want to write the same code many times but implement it
  // for both classes at once in some common way
end;

How can I do this?

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

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

发布评论

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

评论(2

吝吻 2025-01-02 03:00:22

使用三个方法签名定义一个接口,例如IDoSomething

然后将您的类声明更改为

TMyCheckBox = class(TCheckBox, IDoSomething)

然后实施。

如果实现很常见或非常接近。

然后定义一个辅助类 TDoSomething 并委派工作。

例如

Procedure TMyCheckBox.DoSomething1; // implements IDoSomething1
Begin
  TDoSomething.DoSomething1(Self); // given class method will suffice.
End;

delphi中的类方法,相当于其他语言中的静态方法。

Type
    TDoSomethingHelper = Class(TObject)
    Public
      Class Procedure DoSomething1(aComponent : TComponent);
    End;

...
implementation

Class Procedure TDoSomethingHelper.DoSomething1(aComponent : TComponent);
Begin
  aComponent.Tag = 27;
End;

Define an interface say IDoSomething with the the three method signatures.

Then change your class declaration to

TMyCheckBox = class(TCheckBox, IDoSomething)

and then implement.

If the implementations are common or very close.

Then define a helper class TDoSomething and then delegate the work.

e.g.

Procedure TMyCheckBox.DoSomething1; // implements IDoSomething1
Begin
  TDoSomething.DoSomething1(Self); // given class method will suffice.
End;

Class Methods in delphi, equivalent to static methods in other languages.

Type
    TDoSomethingHelper = Class(TObject)
    Public
      Class Procedure DoSomething1(aComponent : TComponent);
    End;

...
implementation

Class Procedure TDoSomethingHelper.DoSomething1(aComponent : TComponent);
Begin
  aComponent.Tag = 27;
End;
弱骨蛰伏 2025-01-02 03:00:22

您正在寻找实现继承而不是接口继承。只有当您可以从单个共同祖先派生类时,这才可以在 Delphi 中实现。此限制是固有的,因为该语言仅支持单继承。

您能做的最好的事情是这样的:

type
  TMyWinControlExtender = class
  private
    FTarget: TWinControl;
  public
    constructor Create(Target: TWinControl);
    procedure WMSize(var Message: TWMSize; out CallInherited: Boolean);
    procedure DoSomething;
  end;

  TMyCheckBox = class(TCheckBox)
  private
    FExtender: TMyWinControlExtender;
  protected
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure DoSomething;
  end;

  TMyRadioButton = class(TRadioButton)
  private
    FExtender: TMyWinControlExtender;
  protected
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure DoSomething;
  end;

{ TMyWinControlExtender }

constructor TMyWinControlExtender.Create(Target: TWinControl);
begin
  inherited Create;
  FTarget := Target;
end;

procedure TMyWinControlExtender.WMSize(var Message: TWMSize; out CallInherited: Boolean);
begin
  if FTarget.... then
    ....
  CallInherited := ...;
  //etc.
end;

procedure TMyWinControlExtender.DoSomething;
begin
  if FTarget.... then
    ....
  //etc.
end;

{ TMyCheckBox }

constructor TMyCheckBox.Create(AOwner: TComponent);
begin
  inherited;
  FExtender := TMyWinControlExtender.Create(Self);
end;

destructor TMyCheckBox.Destroy;
begin
  FExtender.Free;
  inherited;
end;

procedure TMyCheckBox.DoSomething;
begin
  FExtender.DoSomething;
end;

procedure TMyCheckBox.WMSize(var Message: TWMSize);
var
  CallInherited: Boolean;
begin
  FExtender.WMSize(Message, CallInherited);
  if CallInherited then
    inherited;
end;

对于 TMyRadioButton 等也是如此。

现在,您可以使用接口和委托来减少一些样板文件,但没有办法帮助消息处理程序就像WMSize

You are looking for implementation inheritance rather than interface inheritance. This is only achievable in Delphi if you can derive classes from a single common ancestor. This limitation is inherent because the language only supports single-inheritance.

The best you can do is something like this:

type
  TMyWinControlExtender = class
  private
    FTarget: TWinControl;
  public
    constructor Create(Target: TWinControl);
    procedure WMSize(var Message: TWMSize; out CallInherited: Boolean);
    procedure DoSomething;
  end;

  TMyCheckBox = class(TCheckBox)
  private
    FExtender: TMyWinControlExtender;
  protected
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure DoSomething;
  end;

  TMyRadioButton = class(TRadioButton)
  private
    FExtender: TMyWinControlExtender;
  protected
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure DoSomething;
  end;

{ TMyWinControlExtender }

constructor TMyWinControlExtender.Create(Target: TWinControl);
begin
  inherited Create;
  FTarget := Target;
end;

procedure TMyWinControlExtender.WMSize(var Message: TWMSize; out CallInherited: Boolean);
begin
  if FTarget.... then
    ....
  CallInherited := ...;
  //etc.
end;

procedure TMyWinControlExtender.DoSomething;
begin
  if FTarget.... then
    ....
  //etc.
end;

{ TMyCheckBox }

constructor TMyCheckBox.Create(AOwner: TComponent);
begin
  inherited;
  FExtender := TMyWinControlExtender.Create(Self);
end;

destructor TMyCheckBox.Destroy;
begin
  FExtender.Free;
  inherited;
end;

procedure TMyCheckBox.DoSomething;
begin
  FExtender.DoSomething;
end;

procedure TMyCheckBox.WMSize(var Message: TWMSize);
var
  CallInherited: Boolean;
begin
  FExtender.WMSize(Message, CallInherited);
  if CallInherited then
    inherited;
end;

And likewise for TMyRadioButton etc.

Now, you could use interfaces and delegation to reduce some of the boilerplate, but there's no way for that to help with a message handler like WMSize.

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