【问题标题】:How to implement identical methods with 2 and more Classes?如何使用 2 个或更多类实现相同的方法?
【发布时间】:2012-01-10 14:09:08
【问题描述】:

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

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;

我该怎么做?

【问题讨论】:

  • 你是指相同的声明(使用接口)还是相同的实现(使用相同的祖先)?
  • @Krom,这是个好问题。我实际上的意思是相同的实现。
  • 您必须向我们展示实现以获得有效答案。

标签: delphi delphi-7


【解决方案1】:

使用三个方法签名定义一个接口,比如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;

【讨论】:

  • 如何在 D7 中定义这样的辅助类? DoSomething1 应该是类方法吗?
  • 如果我可以创建一个过程,例如:Procedure DoSomething1(aComponent : TComponent);,这正是我现在在我的项目中所做的事情,我可以从静态方法中获得什么?
  • @user 类似于源单元,助手类将相关的助手方法放在一个逻辑组中,但你是对的,区别不大
  • 使用接口意味着您可以将引用作为 IDoSomething 传递给任一组件的实例。使用辅助类静态或其他方式意味着您实现一次并委托两次。如果不知道“常用”方法的作用以及您打算如何调用它们,就无法再进一步了。不呈现 this 是唯一的方法,只是一些你可以用来做这类事情的语言结构。
【解决方案2】:

您正在寻找实现继承而不是接口继承。如果您可以从一个共同的祖先派生类,这只有在 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 这样的消息处理程序。

【讨论】:

  • 10x 大卫。这段代码看起来非常好,特别是你如何处理 WMSize。它可以通过简单的类方法/或 TProcedure(传递Self 作为参考)或多或少地完成我今天正在做的事情。我希望的是“多继承”(使用接口),但现在我明白这里没有魔法。
  • 确实如此。 Delphi 中没有实现的多重继承。很少有语言支持这一点,事实上,它带来的麻烦往往超出其价值。
猜你喜欢
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
  • 2015-09-01
相关资源
最近更新 更多