オブジェクトの生成

クラス型変数の宣言と実際にオブジェクトが生成されることとは別の事だという事を理解してください。クラス型の変数を宣言しただけでは、オブジェクトは生成されてはいないのです。

type
  TBook = class(TObject)
  private
    FNumber: Integer;
  public
    procedure ShowNumber;
  end;

........................

procedure TBook.ShowNumber;
begin
  ShowMessage(IntToStr(FNumber));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Book: TBook; // クラス型変数を宣言
begin
  Book.ShowName; // まちがい!オブジェクトは、生成されていません。

  Book := TBook.Create; // オブジェクトの生成
  Book.ShowNumber;      // メソッドにアクセス
  Book.Free;            // 使い終わったら破棄
end;

クラス型変数( ここでは Book ) を宣言しただけでは、オブジェクトはまだ生成されていません。つまり、この宣言はBook が「 TBook 型のオブジェクトへの参照( この参照については、後でもう少し詳しく解説します。) を保持できる変数である」という事以外の意味を持ちません。ですからコンストラクタで「オブジェクトの生成」、そしてオブジェクトが不要になったらデストラクタで「オブジェクトの破棄」を必ず行ってください。

次に、コンストラクタでの初期化ですが、TBook 型のオブジェクトを生成した後、メソッドShowNumber を呼び出しています。この ShowmNuber では、フィールド FNumber にアクセスしています。

さて、ShowNumber では、なんと表示されるでしょうか?もし、ButtonClick イベントハンドラのなかで、局所変数 i: Integer を宣言した場合には、使用する前に必ず初期化をしなければなりませんでした。今回の FNumber のケースも初期化を行わなければならないのですが、明示的に初期化をしない場合でも FNumber は、0 に初期化されています。実際、オブジェクトを生成する時にコンストラクタがフィールドを初期化してくれています。もちろん、例えばオブジェクトを生成した時に FNumber を 100 に初期化したい場合は、それをコンストラクタに書いてやれば任意の値に初期化することが出来ます。以下の例を見てください。

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

  TBook = class(TObject)
  private
    FNumber: Integer;
  public
    constructor Create; // コンストラクタ
    procedure ShowNumber;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBook }

constructor TBook.Create;
begin
  FNumber := 100; // 100 で初期化
end;

procedure TBook.ShowNumber;
begin
  ShowMessage(IntToStr(FNumber));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Book: TBook;
begin
  Book := TBook.Create;
  Book.ShowNumber;
  Book.Free;
end;

あくまで、明示的に初期化をしない場合にはコンストラクタが自動的に初期化 (本当は、0 に初期化されてから、FNumber := 100; が実行されています) をしてくれているということです。

ここでグローバル変数、局所変数についても復習してみましょう。

var
  Tmp: Integer = 100;
  Number: Integer;

procedure TForm1.Button1Click(Sender: TObject);
var
  Time: Integer;
begin
  Time := 20; // 必ず使う前に初期化をします
  ShowMessage(IntToStr(Time));

  ShowMessage(IntToStr(Tmp));    // OK!
  ShowMessage(IntToStr(Number)); // OK!
end;

明示的に初期化されていないグローバル変数も 0 に初期化されています。


up next
Last update: 2002/7/24