当前位置 : 主页 > 编程语言 > delphi >

delphi – 覆盖构造错误

来源:互联网 收集:自由互联 发布时间:2021-06-23
我是Delphi编码的新手,在尝试覆盖构造函数时遇到错误,你能告诉我我做错了什么或者我应该做些什么来达到预期的结果. 我想覆盖一个框架的构造函数,以便它可以将标签的Caption包含在特
我是Delphi编码的新手,在尝试覆盖构造函数时遇到错误,你能告诉我我做错了什么或者我应该做些什么来达到预期的结果.

我想覆盖一个框架的构造函数,以便它可以将标签的Caption包含在特定文本中.

这是代码

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解释了为什么你的覆盖不起作用.基本上,无论何时覆盖虚方法,两种方法的签名必须完全匹配.但是,我强烈反对使用重新引入.我将在这个答案的底部解释为什么. (请注意,重新引入非常具体,不会覆盖祖先方法.它只隐藏该方法隐藏祖先方法的警告.)

几个更好的选择:

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

您不必为构造函数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;

重新引入有什么问题?

>重新引入仅适用于基类上的方法是虚拟的.
>如果打算以多态方式使用该方法,则该方法应该是虚拟的.
>这意味着该方法旨在从基类引用中调用,但可能需要采取特殊操作才能在某些子类中正常工作.

由于您的问题涉及覆盖TComponent.Create,因此通过示例的方式可以很好地说明.

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

网友评论