Frage

Update: Das Beispiel war ich ursprünglich hatte Art komplexer. Hier ist ein einfache 8-Zeilen-Beispiel, das alles in einem Codeblock erklärt. Der folgende nicht Compile gibt eine Warnung aus:

TComputer = class(TObject)
public
    constructor Create(Cup: Integer); virtual;
end;

TCellPhone = class(TComputer)
public
    constructor Create(Cup: Integer; Teapot: string); virtual;
end;

Hinweis: Diese Frage ist Teil 3 in meiner laufenden Reihe von Fragen über die subtlties von Konstrukteuren in Delphi

Original Frage

Wie kann ich einen Konstruktor zu einer vorhandenen Klasse hinzufügen?

Lassen Sie uns geben, ein hypothetisches Beispiel (das heißt eine, die ich hier oben im SO-Editor tippen bin so kann es oder nicht kompilieren):

TXHTMLStream = class(TXMLStream)
public
   ...
end;

Ferner wird angenommen, dass die normale Verwendung von TXHTMLStream viel wiederholtem Code beteiligt Durchführung, bevor sie verwendet werden kann:

var
   xs: TXHTMLStream;
begin
   xs := TXHTMLStream.Create(filename);
   xs.Encoding := UTF32;
   xs.XmlVersion := 1.1;
   xs.DocType := 'strict';
   xs.PreserveWhitespace := 'true';
   ...

   xs.Save(xhtmlDocument);

Nehmen wir an, ich einen Konstruktor erstellen möchten, die alle, dass Text Setup-Code vereinfacht:

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;

Das vereinfacht die Nutzung des Objekts:

var
   xs: TXHTMLStream;
begin
   xs := TXHTMLStream.Create(filename, UTF32);
   xs.Save(xhtmlDocument);

Außer jetzt Delphi beklagt, dass mein neuer Konstruktor versteckt die alte Konstruktor.

  

Die Methode 'Create' Häute virtuelle Methode des Basistypen 'TXMLStream'

ich habe sicher nicht mittlere verstecken die Vorfahren schaffen -. I wollen beide

Wie füge ich einen Konstruktor (mit andere Signatur) zu einer abgeleiteten Klasse, während der Vorfahren Konstruktor zu halten, so dass es nach wie vor verwendet werden kann?

War es hilfreich?

Lösung

Meine unmittelbare Reaktion ist das overload Schlüsselwort zu verwenden, wie in:

TCellPhone = class(TComputer)
public
    constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;

Bearbeiten : Danke Ian für die Bearbeitung, die eine Antwort aus meiner Antwort macht. Ich würde gerne glauben, dass ich es bekam für Tapferkeit, so dass ich ein vollständigeres Beispiel dazu beitragen werde:

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.

mit dem Ergebnis,:

constructed computer: cup = 1

constructed computer: cup = 2

constructed computer: cup = 3
constructed cellphone: Teapot = kettle

Andere Tipps

Sie können zwei neue ladenen Konstruktoren erstellen, zum Beispiel:

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;

Ein andere Möglichkeit ist es, einen neuen Konstruktor mit Standard-Parameterwerten zu schreiben, wo der Teil der Signatur mit Nicht-Standard-Parametern entspricht den ursprünglichen Konstruktor in der Basisklasse:

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;

Denken Sie auch daran, dass Konstrukteure haben nicht erstellen aufgerufen werden. Ältere Versionen von Delphi nicht Methodenüberladung, so dass Sie verschiedene Namen verwenden haben:

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;

Die beiden Konstrukteure werden nun zur Verfügung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top