継承と仮想メソッド

継承、仮想メソッド、override、reintroduce

クラス継承のサンプル

Object Pascalは継承と仮想メソッドに対応しています。下記サンプルではTDogがTAnimalを継承します:

TDogはサブクラス(派生クラス)、TAnimalは親クラス(基底クラス)です

program AnimalDemo;
{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
{$codepage utf8}
uses SysUtils;

type
  // 動物親クラス
  TAnimal = class
    procedure Cry; virtual; // 仮想メソッド:動物の鳴き声
  end; // クラス定義終了、end;のみ記述

  // 犬のサブクラス、動物を継承し鳴き声をオーバーライド
  TDog = class(TAnimal)
    procedure Cry; override;
  end;

procedure TAnimal.Cry;
begin
  WriteLn('動物が鳴きます');
end;

procedure TDog.Cry;
begin
  WriteLn('ワンワンワン');
end;

var
  Pet: TAnimal;
begin
  // 親クラスインスタンス
  Pet := TAnimal.Create;
  try
    Pet.Cry;
  finally
    FreeAndNil(Pet);
  end;

  // サブクラスインスタンスを親クラス変数に代入、ポリモーフィズムが有効化
  Pet := TDog.Create;
  try
    Pet.Cry;
  finally
    FreeAndNil(Pet);
  end;
end.Code language: JavaScript (javascript)

実行結果

D:\fpcdemo>fpc mydemo.dpr
Free Pascal Compiler version 3.2.2 [2021/05/15] for i386
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling mydemo.dpr
Linking mydemo.exe
45 lines compiled, 0.1 sec, 68544 bytes code, 4260 bytes data

D:\fpcdemo>mydemo
動物が鳴きます
ワンワンワンCode language: CSS (css)

FreeAndNil

オブジェクトを安全に解放、2つの処理を1つにまとめます:

  1. オブジェクトのFreeを呼び出しメモリを破棄;
  2. 変数をnilに代入し、ダングリングポインタを防止。

上記コードではサブクラスTDogのオブジェクトをTAnimal型変数Petに格納しています。PetからCryを呼び出す際、TAnimalのCryではなくTDog内のCryが実行されます。これがポリモーフィズムです。

  • Cry; virtual:親クラスメソッドを仮想とし、実行時ポリモーフィズムを有効に;
  • サブクラスはoverrideCryを上書き;
  • 変数宣言型はTAnimalだが実体はTDogなので、犬の鳴き声処理が自動実行される。

virtual付きメソッド:コンパイラは実行時にオブジェクトの実際の型に基づき対応するメソッド実装を解決します。

virtualoverrideを削除した場合

2回の呼び出しがいずれも親クラスのメソッドを実行します

上図はvirtualoverrideを削除した後の画面です

出力はすべてTAnimalの実装となる

コンパイラは変数の宣言型TMyClassのみ参照し、オブジェクトの実行時型を無視します。

  • 通常メソッドは既定で非仮想、virtualを付加すると仮想メソッドになる;
  • サブクラスで親の仮想メソッドを上書きするにはoverrideが必須、無いとコンパイラが警告を出力;
  • 親クラスの同名仮想メソッドを隠蔽し上書きしない場合はreintroduceを使用(混乱を招くため非推奨)、C#のnewキーワードに相当

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です