繼承與虛方法

繼承、虛方法、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

安全釋放物件,合併兩個動作:

  1. 呼叫物件 Free 釋放記憶體;
  2. 將變數設為 nil,避免產生野指標。

上方程式碼將子類別 TDog 的物件存放在 TAnimal 型別變數 Pet 中,後續透過 Pet 呼叫 Cry 時,實際執行 TDog 內的 Cry 而非 TAnimal 的 Cry,此特性即為多型。

  • Cry; virtual 標記父類方法為虛方法,開啟執行期多型;
  • 子類使用 override 覆寫 Cry
  • 變數宣告型別為 TAnimal,但實體為 TDog,自動執行狗的叫聲實作。

標記 virtual 的方法:編譯器會在執行期依照物件實際型別對應正確的方法實作。

若移除 virtualoverride

兩次呼叫都會執行父類別方法

上圖為刪除 virtualoverride 後的執行畫面

輸出內容全部來自 TAnimal 的實作

編譯器只辨識變數宣告型別 TMyClass,忽略物件執行期真實型別。

  • 一般方法預設非虛方法,加上 virtual 才會成為虛方法;
  • 子類覆寫父類虛方法必須加上 override,否則編譯器會發出警告;
  • 若要隱藏父類同名虛方法、不進行覆寫,可使用 reintroduce(不建議,容易造成混淆),等同 C# 的 new 關鍵字

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *