inherited

inherited は、「上位クラスから継承したメソッドの呼び出し」ということをまず頭に入れておいて下さい。早速例を見てみましょう。

inherited の後ろに引数を伴わないケース

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  TBase = class(TObject)
  public
    procedure ShowName;
  end;

  TDerived = class(TBase) // TBase から派生
  public
    procedure ShowName;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBase }

procedure TBase.ShowName;
begin
  Form1.ListBox1.Items.Add('Base');
end;

{ TDerived }

procedure TDerived.ShowName;
begin
  inherited; // 上位クラスのメソッドの呼び出し。
  Form1.ListBox1.Items.Add('Derived');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Derived: TDerived;
begin
  Derived := TDerived.Create; (* ブレークポイント *)
  Derived.ShowName;
  Derived.Free;
end;

end.

結果は、以下のようになります。

上記のプログラムの中で、「(* ブレークポイント *)」とコメントしてある場所にブレークポイントを設置して F7 キーを押していってみてください。コードの実行手順を見る事が出来ます。

inherited についてですが、冒頭でも述べてあるように上位クラスから継承したメソッドの呼び出しを行っています。まず初めに、Button1 をクリックして実行されるコードから見ていきます。

procedure TForm1.Button1Click(Sender: TObject);
var
  Derived: TDerived;
begin
  Derived := TDerived.Create;
  Derived.ShowName;
  Derived.Free;
end;

まず、TDerived 型の変数 Derived を宣言しています。次に、TDerived クラスのオブジェクトを生成し、それを Derived 変数に代入しています。(厳密に言うと、クラス型の変数はポインタです。ここでは単に、クラス型の変数はポインタと言う事だけ、覚えておいて下さい。)

Derived 変数は、TDerived 型のオブジェクトを参照しているので、Derived.ShowName では、TDerived 型で定義してあるメソッドが呼ばれることになります。つまり以下のコードが呼ばれることになります。

procedure TDerived.ShowName;
begin
  inherited;
  Form1.ListBox1.Items.Add('Derived');
end;

ここで、inherited; が宣言されています。まず結論から述べますと、この inherited; は、TBase.ShowName; を呼び出します。

何故 TBase.ShowName が呼ばれるのか?
inherited を記述する際には、inherited の後ろに引数を伴う場合と、伴わない場合があります。ここでは、inherited の後ろに引数を伴わないケースの例と言う事になります。このように引数を省略した場合には、記述中のメソッド(ここでは ShowName メソッドのことです。) と同じ識別子を持つ上位クラスのメソッドが呼ばれることになります。もし、上位クラスに記述中のメソッドと同名のメソッドが無ければ inherited は、単に無視されます。

図にしますと、以下のような感じになります。

文字色を「青」にしたところに注目してください。inherited; が記述されている所で実行されるコードは、それが記述されているメソッド名(ここでは、ShowName )と同じ識別子が上位クラスにあれば、その上位クラスのメソッドが呼び出されます。ここでは、TDerived の上位クラスの TBase クラスに、記述中の手続きと同じ名前のメソッド( ShowName )があります。ですから、TBase.ShowName が呼び出されることになります。

もし、同名のメソッド名が上位クラスに無ければ、Delphi は、inherited を無視します。以下の例を見てください。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  TBase = class(TObject)
  public
    procedure ShowName;
  end;

  TDerived = class(TBase)
  public
    procedure ShowName2; // 若干、名前が変わりました。
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBase }

procedure TBase.ShowName;
begin
  Form1.ListBox1.Items.Add('Base');
end;

{ TDerived }

procedure TDerived.ShowName2;
begin
  inherited; // この inherited は、無視されます。
  Form1.ListBox1.Items.Add('Derived');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Derived: TDerived;
begin
  Derived := TDerived.Create;
  Derived.ShowName2;
  Derived.Free;
end;

end.

結果は以下のようになります。

TDerived.ShowName2 メソッドの中で、inherited を使用していますが、この TDerived クラスの上位クラスには、ShowName2 という名前をもつメソッドはありません。ですから、この場合の inherited は無視される事になります。

メソッドがパラメータ(引数)を持つ場合

それでは、メソッドがパラメータ(引数)を持つ場合に、inherited を使用するとどうなるのでしょうか。以下の例を見てください。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  TBase = class(TObject)
  public
    procedure ShowName(name: string); // 引数を持ちます。
  end;

  TDerived = class(TBase)
  public
    procedure ShowName(name: string); // 引数を持ちます。
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBase }

procedure TBase.ShowName(name: string);
begin
  Form1.ListBox1.Items.Add('Base'+name);
end;

{ TDerived }

procedure TDerived.ShowName(name: string);
begin
  inherited; // メソッド呼び出しで、引数はどうなる?
  Form1.ListBox1.Items.Add('Derived'+name);
end;

procedure TForm1.Button1Click(Sender:TObject);
var
  Derived: TDerived;
begin
  Derived := TDerived.Create;
  Derived.ShowName('--Hello!--');
  Derived.Free;
end;

end.

結果は以下のようになります。

結果を見てみますと、上位クラスのメソッドが呼び出されるとき、つまり TBase.ShowName(name: string) が呼び出されるとき、呼び出し元に与えられたパラメータが渡されている事が分かります。

inherited の後ろに引数を伴うケース

inherited の後ろに引数を伴う場合でも、基本的なことは変わりません。冒頭でも述べたとおり上位クラスから継承したメソッドの呼び出しが inherited の役目です。引数には、どのメソッドを呼び出すかを指定してやる事になります。早速例を見てみましょう。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  TBase = class(TObject)
  public
    procedure ShowName;
  end;

  TDerived = class(TBase)
  public
    procedure ShowName;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBase }

procedure TBase.ShowName;
begin
  Form1.ListBox1.Items.Add('Base');
end;

{ TDerived }

procedure TDerived.ShowName;
begin
  inherited ShowName; // 引数を指定しています。
  Form1.ListBox1.Items.Add('Derived');
end;

procedure TForm1.Button1Click(Sender:TObject);
var
  Derived: TDerived;
begin
  Derived := TDerived.Create;
  Derived.ShowName;
  Derived.Free;
end;

end.

結果は、以下のようになります。

この場合は、一番最初の例と全く同じになります。inherited の後ろに引数を指定すると、上位クラスのどのメソッドを呼び出すのかを指定しているだけです。ここでは、記述中のメソッド( TDerived.ShowName ) と、呼び出そうとするメソッド名が同じなので、inherited の後ろの引数を省略した場合と全く同じになります。

引数を指定する場合には、上位クラスのどのメソッドを呼び出すかを指定できますので、以下のようなことができるようになります。

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  TBase = class(TObject)
  public
    procedure ShowName;
    procedure ShowClass;
  end;

  TDerived = class(TBase)
  public
    procedure ShowName;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBase }

procedure TBase.ShowClass;
begin
  Form1.ListBox1.Items.Add('Base-ShowClass')
end;

procedure TBase.ShowName;
begin
  Form1.ListBox1.Items.Add('Base-ShowName');
end;

{ TDerived }

procedure TDerived.ShowName;
begin
  inherited ShowClass; // 引数を指定しています。
  Form1.ListBox1.Items.Add('Derived-ShowName');
end;

procedure TForm1.Button1Click(Sender:TObject);
var
  Derived: TDerived;
begin
  Derived := TDerived.Create;
  Derived.ShowName;
  Derived.Free;
end;

end.

結果は、以下のようになります。

inherited の後ろの引数に注目してください。このように上位クラスのどのメソッドを呼び出すかを指定しています。

メソッドがパラメータ(引数)を持つ場合

inheited の後ろで指定するメソッドがパラメータを持つ場合の例です。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  TBase = class(TObject)
  public
    procedure ShowName(name: string);
    procedure ShowNumber(int: Integer);
  end;

  TDerived = class(TBase)
  public
    procedure SimpleMethod1;
    procedure SimpleMethod2;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBase }


procedure TBase.ShowName(name: string);
begin
  Form1.ListBox1.Items.Add('Base '+name);
end;

procedure TBase.ShowNumber(int: Integer);
begin
  Form1.ListBox1.Items.Add('Base '+IntToStr(int));
end;

{ TDerived }

procedure TDerived.SimpleMethod1;
begin
  inherited ShowName('Test');
  Form1.ListBox1.Items.Add('TDerived.SimpleMethod1');
end;

procedure TDerived.SimpleMethod2;
begin
  inherited ShowNumber(2002);
  Form1.ListBox1.Items.Add('TDerived.SimpleMethod2')
end;

procedure TForm1.Button1Click(Sender:TObject);
var
  Derived: TDerived;
begin
  Derived := TDerived.Create;
  Derived.SimpleMethod1;
  ListBox1.Items.Add('========');
  Derived.SimpleMethod2;
  Derived.Free;
end;

end.

結果は、以下のようになります。

inherited の後ろでメソッドを指定するときに引数を指定してやる事で、上位クラスのメソッド呼び出し時に、その指定した引数を渡す事になります。

inherited を記述する位置により、実行順序を変える。

メソッド内で inherited を記述する位置を変更することで、実行順序を変える事ができます。つまり、上位クラスのメソッドを最初に実行するのか、或いは、最後に実行するのか等を調整することができます。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  TBase = class(TObject)
  public
    procedure ShowName;
  end;

  TDerived1 = class(TBase)
  public
    procedure ShowName;
  end;

  TDerived2 = class(TBase)
  public
    procedure ShowName;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBase }

procedure TBase.ShowName;
begin
  Form1.ListBox1.Items.Add('Base');
end;

{ TDerived1 }

procedure TDerived1.ShowName;
begin
  inherited;
  Form1.ListBox1.Items.Add('Derived1');
end;

{ TDerived2 }

procedure TDerived2.ShowName;
begin
  Form1.ListBox1.Items.Add('Derived2');
  inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Derived1: TDerived1;
  Derived2: TDerived2;
begin
  Derived1 := TDerived1.Create;
  Derived1.ShowName;
  Derived1.Free;

  ListBox1.Items.Add('========');

  Derived2 := TDerived2.Create;
  Derived2.ShowName;
  Derived2.Free;
end;

end.

結果は、以下のようになります。

このように、inherited の位置により実行順序を変える事が可能です。

メッセージハンドラ内での inherited

メッセージハンドラ内の inherited でメソッド名が指定されていない場合、同じメッセージ番号を持つ上位クラスのメッセージハンドラが呼び出されます。同じメッセージ番号をもつメッセージハンドラが上位クラスにない場合、Delphi は DefaultHander を呼び出します。また、メッセージハンドラのメソッド名は、必ずしも上位クラスのメソッド名と同じでなくても構いません。


up next
Last update: 2002/10/14