Update: The example i originally had was kind of complex. Here\'s a simple 8 line example that explains everything in one code block. The following
Also remember that constructors don't HAVE to be called Create. Older versions of Delphi didn't have method overloading, so you had to use different names:
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;
Both constructors will now be available.
My immediate reaction is to use the overload
keyword, as in:
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;
Edit: Thanks Ian for the edit, which makes an answer out of my answer. I would like to think that I got it for bravery, so I am going to contribute a fuller example:
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.
with the result being:
constructed computer: cup = 1
constructed computer: cup = 2
constructed computer: cup = 3
constructed cellphone: Teapot = kettle
You could create two new overloaded constructors, for example:
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;
Another possibility is to write a new constructor with default parameter values where the part of the signature with non-default parameters matches the original constructor in the base class:
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;