更新:我最初的例子有点复杂。这是一个简单的8行示例,它解释了一个代码块中的所有内容。以下不编译会发出警告:
TComputer = class(TObject)
public
constructor Create(Cup: Integer); virtual;
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); virtual;
end;
注意:这个问题是我正在进行的一系列有关Delphi中构造函数的子句的问题的第3部分
如何将构造函数添加到现有类?
让我们举一个假设的例子(即我在SO编辑器中输入的那个例子,它可能编译也可能不编译):
TXHTMLStream = class(TXMLStream)
public
...
end;
进一步假设正常使用TXHTMLStream
涉及在使用之前执行大量重复代码:
var
xs: TXHTMLStream;
begin
xs := TXHTMLStream.Create(filename);
xs.Encoding := UTF32;
xs.XmlVersion := 1.1;
xs.DocType := 'strict';
xs.PreserveWhitespace := 'true';
...
xs.Save(xhtmlDocument);
假设我想创建一个简化所有样板设置代码的构造函数:
TXHTMLStream = class(TXMLStream)
public
constructor Create(filename: string; Encoding: TEncoding); virtual;
end;
constructor TXHTMLStream.Create(filename: string; Encoding: TEncoding);
begin
inherited Create(filename);
xs.Encoding := Encoding;
xs.XmlVersion := 1.1;
xs.DocType := 'strict';
xs.PreserveWhitespace := True;
...
end;
这简化了对象的使用:
var
xs: TXHTMLStream;
begin
xs := TXHTMLStream.Create(filename, UTF32);
xs.Save(xhtmlDocument);
除了现在Delphi抱怨我的新构造函数隐藏了旧的构造函数。
方法'Create'隐藏基类型'TXMLStream'的虚拟方法
我当然没有 意味着 隐藏祖先创建 - 我 想要 两者。
如何将一个构造函数(带有不同的签名)添加到后代类中,同时保留祖先构造函数以便仍然可以使用它?
答案 0 :(得分:8)
我的立即反应是使用overload
关键字,如:
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;
编辑:感谢Ian的编辑,这是我的回答。我想我是勇敢的,所以我将提供一个更全面的例子:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TComputer = class(TObject)
public
constructor Create(Cup: Integer); virtual;
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;
{ TComputer }
constructor TComputer.Create(Cup: Integer);
begin
writeln('constructed computer: cup = ', Cup);
end;
{ TCellPhone }
constructor TCellPhone.Create(Cup: Integer; Teapot: string);
begin
inherited Create(Cup);
writeln('constructed cellphone: Teapot = ', Teapot);
end;
var
C1, C2, C3: TComputer;
begin
C1 := TComputer.Create(1);
Writeln;
C2 := TCellPhone.Create(2);
Writeln;
C3 := TCellPhone.Create(3, 'kettle');
Readln;
end.
结果为:
constructed computer: cup = 1
constructed computer: cup = 2
constructed computer: cup = 3
constructed cellphone: Teapot = kettle
答案 1 :(得分:3)
您可以创建两个新的重载构造函数,例如:
type
TXmlStream = class
private
FFileName: string;
public
constructor Create(const AFileName: string); virtual;
end;
TXhtmlStream = class(TXmlStream)
private
FEncoding: TEncoding;
public
constructor Create(const AFileName: string); overload; override;
constructor Create(const AFileName: string; AEncoding: TEncoding); overload; virtual;
end;
constructor TXmlStream.Create(const AFileName: string);
begin
inherited Create;
FFileName := AFileName;
end;
constructor TXhtmlStream.Create(const AFileName: string);
begin
inherited Create(AFileName);
end;
constructor TXhtmlStream.Create(const AFileName: string; AEncoding: TEncoding);
begin
inherited Create(AFileName);
FEncoding := AEncoding;
end;
答案 2 :(得分:1)
另一种可能性是编写一个带有默认参数值的新构造函数,其中带有非默认参数的签名部分与基类中的原始构造函数匹配:
type
TXmlStream = class
private
FFileName: string;
public
constructor Create(const AFileName: string); virtual;
end;
TXhtmlStream = class(TXmlStream)
private
FEncoding: TEncoding;
public
constructor Create(const AFileName: string; AEncoding: TEncoding = encDefault); reintroduce; virtual;
end;
constructor TXmlStream.Create(const AFileName: string);
begin
inherited Create;
FFileName := AFileName;
end;
constructor TXhtmlStream.Create(const AFileName: string; AEncoding: TEncoding);
begin
inherited Create(AFileName);
FEncoding := AEncoding;
end;
答案 3 :(得分:1)
还要记住构造函数不必称为Create。较旧版本的Delphi没有方法重载,因此您必须使用不同的名称:
TComputer = class(TObject)
public
constructor Create(Cup: Integer); virtual;
end;
TCellPhone = class(TComputer)
private
FTeapot: string;
public
constructor CreateWithTeapot(Cup: Integer; Teapot: string); virtual;
end;
...
constructor TCellPhone.CreateWithTeapot(Cup: Integer; Teapot: string);
begin
Create(Cup);
FTeapot := Teapot;
end;
两个构造函数现在都可用。