8

更新:私が最初に持っていた例は、ちょっと複雑でした。これは、1つのコードブロックですべてを説明する簡単な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は私の新しいコンストラクターが古いコンストラクターを隠していると不平を言います。

メソッド「作成」は、基本タイプ「TXMLStream」の仮想メソッドを非表示にします

私は確かに祖先の作成を隠すつもりはありませんでした-は両方が欲しいです。

祖先コンストラクターを保持したまま、子孫クラスに(異なるシグネチャを持つ)コンストラクターを追加して、引き続き使用できるようにするにはどうすればよいですか?

4

4 に答える 4

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
于 2010-10-06T20:30:52.857 に答える
3

次に、2つの新しいオーバーロードされたコンストラクターを作成できます。

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;
于 2010-10-06T20:48:12.860 に答える
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;
于 2010-10-06T20:54:55.623 に答える
2

また、コンストラクターは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;

これで、両方のコンストラクターが使用可能になります。

于 2010-10-06T21:14:37.440 に答える