delphi - 覆盖构造错误

标签 delphi constructor overriding

我是 Delphi 编码的新手,在尝试重写构造函数时遇到错误,您能否建议我做错了什么,或者我应该做什么才能获得所需的结果。

我想重写框架的构造函数,以便它可以将其包含的标签标题更改为特定文本。

这是代码

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TfrmMesaj = class(TFrame)
    Panel1: TPanel;

  private
    { Private declarations }
  public
    { Public declarations }
    constructor Create(name : string);  override;
  end;

implementation

{$R *.dfm}

{ TfrmMesaj }



{ TfrmMesaj }

constructor TfrmMesaj.Create(name: string);
begin
  inherited;
   Panel1.Color := clRed;
   Panel1.Caption := name;
end;

end.

当我尝试编译时出现以下错误:

[DCC Error] frameMesaj.pas(17): E2037 Declaration of 'Create' differs from previous declaration
[DCC Error] frameMesaj.pas(32): E2008 Incompatible types

我做错了什么以及如何实现我想要的?

最佳答案

Stefan已经解释了为什么你的覆盖不起作用。基本上,每当您重写虚拟方法时,两个方法的签名都必须完全匹配。但是,我强烈反对使用 reintroduce 。我将在这个答案的底部解释原因。 (另请注意,重新引入非常明确不会覆盖祖先方法。它仅隐藏警告该方法隐藏祖先的方法。)

几个更好的选择:

为构造函数使用不同的名称

您不必将构造函数命名为 Create 。例如,您可以添加第二个构造函数: constructor CreateWithCaption(AName: string); 。请注意,我什至没有将此构造函数设为虚拟。仅当您希望方法具有多态性时才将其设为虚拟方法。 (这意味着您希望子类即使从基类调用时也能够更改实现。)

此选项非常类似于 Stefan 建议的重载

使用工厂方法创建框架

随着系统变得越来越大,将创建某些对象的处理与它们实际执行的工作分开会很有用。这是使用工厂方法完成的,工厂方法的唯一目的是创建准备与系统其余部分交互的其他对象。例如

//I've chosen to demonsrate this on a form, but you could also implement a dedicated factory class
function TMyForm.CreateMessageFrame(ACaption: string): TFrame;
begin
  //Note the factory method intends the form to own all frames created.
  Result := TfrmMesaj.Create(Self);
  
  //The factory method ensures the frame is "ready"
  //This does violate Law of Demeter, but you could easily add a method to the fram to resolve that.
  Result.Panel1.Color := clRed;
  Result.Panel1.Caption := ACaption;
end;
<小时/>

reintroduce 有什么问题吗?无论如何?

  • Reintroduce 仅适用于基类上的方法为 virtual 的情况。
  • 仅当打算多态使用时,该方法才应该是虚拟的。
  • 这意味着该方法旨在从基类引用中调用,但可能需要采取特殊操作才能在某些子类中正常工作

由于您的问题是处理重写 TComponent.Create ,它可以很好地通过示例进行说明。

  • constructor TComponent.Create(AOwner: TComponent);虚拟,非常具体,因此组件创建的行为是多态的。这样,当组件从 .DFM 文件流式传输时,即使用于创建它们的引用类型为 TComponent,它们也会正确创建。 .
  • 如果隐藏此构造函数,则在流式传输帧并从 .DFM 创建帧时需要执行的任何特殊操作都不会发生。
  • 此外,您的框架的任何子类将无法覆盖 constructor Create(AOwner: TComponent);因为它是隐藏的。

关于delphi - 覆盖构造错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23806739/

相关文章:

c++ - 模板继承

ruby - 在 Ruby 中覆盖 "for"关键字。是否可以?

delphi - Turbo Power - 用于 Delphi XE 的 SongBeamer 或 SourceForge?

delphi - 检查ini文件是否存在delphi

Delphi - 更改任务栏图标

f# - 如何在F#中以复合类型覆盖ToString?

c++ - 以参数为类指针的虚函数

delphi - 串行通信 (RTS) 和 Windows 7

dart - Dart const类参数检查

java - 抽象类中的疑问