警告をなくすには?

解決


@ボーイ  2006-05-02 19:12:38  No: 21280

自アプリ用にパネルのクラスを作っています。
コンパイル時に
≪[警告] TestMain.pas(66): 'Create' メソッドが基本型 'TCustomPanel' の仮想メソッドを隠しました≫
というような警告がでます。以下がコードの一部です。
overload の部分を override に変更すると
≪[エラー] TestMain.pas(63): 'Create' の宣言がすでに定義されているものと異なります≫
となってしまいます。
どのように対処すればよいのでしょうか?

TMyPanel = class (TCustomPanel)
private
  〜<略>〜
public
  〜<略>〜
  constructor Create(AOwner: TComponent; PMain: TPanel); overload;
end;


@ボーイ  2006-05-02 19:17:41  No: 21281

調べてみると見つかりました。
reintroduce;

警告を無視するんですね。
お騒がせしました。


補足  2006-05-07 07:35:42  No: 21282

補足
>reintroduce;
は、上位クラスから呼ばれなくなりますので注意してください。
上位クラスは、上位クラスの段階で実装されたメソッドを呼び出します。

interface
type
  TClassA = class
  private
    FTestValue: integer;
  protected
    function GetValue: integer; virtual;
    procedure SetValue(const Value: integer); virtual;
  public
    constructor Create;
    property TestValue: integer read GetValue write SetValue;
  end;
  TClassB = class( TClassA)
  protected
    procedure SetValue(const Value: integer); override;
  end;
  TClassC = class( TClassA)
  protected
    procedure SetValue(const Value: integer); reintroduce;
  end;
  TForm1省略

implementation
{ TClassA }

constructor TClassA.Create;
begin
    SetValue( 1);
end;

function TClassA.GetValue: integer;
begin
    Result:= FTestValue;
end;

procedure TClassA.SetValue(const Value: integer);
begin
    FTestValue:= Value;
end;

{ TClassB }

procedure TClassB.SetValue(const Value: integer);
begin
  inherited SetValue( Value+1);
  //1足しますが overrideされています。
end;

{ TClassC }

procedure TClassC.SetValue(const Value: integer);
begin
  inherited SetValue( Value+1);
  //1足しますが、reintroduceされています。
end;

//テスト
procedure TForm1.Button1Click(Sender: TObject);
begin
    with TClassA.Create do
    try
        Memo1.Lines.Add( 'CLASS-A '+IntTOStr(TestValue));
    finally
        Free;
    end;
    with TClassB.Create do
    try
        Memo1.Lines.Add( 'CLASS-A OVERRIDE  '+IntTOStr(TestValue));
    finally
        Free;
    end;
    with TClassC.Create do
    try
        Memo1.Lines.Add( 'CLASS-A REINTRODUCE '+IntTOStr(TestValue));
    finally
        Free;
    end;
end;
結果、
CLASS-A 1
CLASS-A OVERRIDE  2
CLASS-A REINTRODUCE 1
となり、
CLASS-A REINTRODUCEは、上位クラスからは呼ばれていないのが確認できます。

したがって reintroduceができるのは、
・上位クラスがそのメソッドを内部から呼んでいない
・上位クラスがそのメソッドを内部から呼んでいても問題ない
場合に限られます。

ちなみに、TCustomPanelの Create は reintroduceを使っても、問題ありません。

しかし、
type
  ClassAClasses = class of TClassA;
  
などとして
  TClassC = class( TClassA)
  protected
    constructor Create; reintroduce; //追加
    procedure SetValue(const Value: integer); reintroduce;
  end;
のように変更。

implementation
              
constructor TClassC.Create;
begin
    inherited;
    SetValue( 100);
end;

//テスト
procedure TForm1.Button2Click(Sender: TObject);

    function CreateClass( SomeClass: ClassAClasses):TClassA;
    begin
        Result:= SomeClass.Create;
    end;
begin
    with CreateClass(TClassA) do
    try
        Memo1.Lines.Add( 'CLASS-A '+IntTOStr(TestValue));
    finally
        Free;
    end;
    with CreateClass(TClassB) do
    try
        Memo1.Lines.Add( 'CLASS-A OVERRIDE  '+IntTOStr(TestValue));
    finally
        Free;
    end;
    with CreateClass(TClassC) do
    try
        Memo1.Lines.Add( 'CLASS-A REINTRODUCE '+IntTOStr(TestValue));
    finally
        Free;
    end;
end;
結果、
CLASS-A 1
CLASS-A OVERRIDE  2
CLASS-A REINTRODUCE 1
となり、TClassCのコンストラクタが呼ばれません。
Class of hoehoe 等を使って動的にクラスを生成したりする場合には、
reintroduceのコンストラクタが 呼び出されないということを
覚えておく必要があると思います。

機転を利かせ、動的にクラスが変化する機構を実装した場合などには
バグになるので注意が必要です(はまります)


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加