首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi override 關鍵字深度解析:虛擬方法覆寫與靜態綁定的行為差異

     編輯:Delphi

Delphi 中 virtual 與 override 是實現多態的核心機制。本文通過一個完整可編譯的範例,詳細演示 override 如何改變方法調用行為,對比虛擬方法與非虛擬方法在繼承鏈中的不同表現,並展示類型轉換對調用的影響。

完整範例代碼

unit Unit1;

interface

uses
  Classes, Controls, Forms, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

  { 基類 }
  TBase = class
    procedure Proc1; virtual;  { 虛擬方法 }
    procedure Proc2;           { 靜態方法 }
  end;

  { 子類 }
  TChild = class(TBase)
    procedure Proc1; override; { 覆寫虛擬方法 }
    procedure Proc2;           { 重新宣告靜態方法(隱藏) }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBase 實現 }
procedure TBase.Proc1;
begin
  ShowMessage('B1');
end;

procedure TBase.Proc2;
begin
  ShowMessage('B2');
end;

{ TChild 實現 }
procedure TChild.Proc1;
begin
  // inherited;  { 可選:呼叫基類實現 }
  ShowMessage('C1');
end;

procedure TChild.Proc2;
begin
  ShowMessage('C2');
end;

{ 測試按鈕 }
procedure TForm1.Button1Click(Sender: TObject);
var
  B: TBase;
  C: TChild;
  BC: TBase;
begin
  B := TBase.Create;
  C := TChild.Create;
  BC := TChild.Create;  { 父類變數持有子類實例 }

  { 直接呼叫 }
  B.Proc1;   // B1
  B.Proc2;   // B2

  { 類型轉換呼叫 }
  TChild(B).Proc1;  // B1  —— B 實際是 TBase,轉型不改變實際類型
  TChild(B).Proc2;  // C2  —— 靜態方法按變數類型綁定,TChild.Proc2

  C.Proc1;   // C1  —— 虛擬方法多態
  C.Proc2;   // C2  —— 靜態方法按實際類型(此處同)

  TBase(C).Proc1;  // C1  —— 虛擬方法多態,實際類型 TChild
  TBase(C).Proc2;  // B2  —— 靜態方法按變數類型 TBase

  BC.Proc1;        // C1  —— 虛擬方法多態
  BC.Proc2;        // B2  —— 靜態方法按變數類型 TBase

  TBase(BC).Proc1; // C1
  TBase(BC).Proc2; // B2

  TChild(BC).Proc1; // C1
  TChild(BC).Proc2; // C2

  B.Free;
  C.Free;
  BC.Free;
end;

end.

執行結果對照表

呼叫代碼輸出說明
B.Proc1B1基類實例呼叫虛擬方法
B.Proc2B2基類實例呼叫靜態方法
TChild(B).Proc1B1轉型不改變實際物件,虛擬方法仍按實際類型
TChild(B).Proc2C2靜態方法按變數聲明類型綁定(TChild)
C.Proc1C1子類實例虛擬方法多態
C.Proc2C2子類實例靜態方法
TBase(C).Proc1C1虛擬方法多態:實際類型 TChild
TBase(C).Proc2B2靜態方法按變數類型 TBase
BC.Proc1C1父類變數持有子類實例,虛擬方法多態
BC.Proc2B2靜態方法按變數類型 TBase
TBase(BC).Proc1C1虛擬方法多態
TBase(BC).Proc2B2靜態方法按 TBase
TChild(BC).Proc1C1虛擬方法多態
TChild(BC).Proc2C2靜態方法按變數類型 TChild

核心規則總結

  1. 虛擬方法(virtual/override):運行時根據實際物件類型分派(動態綁定),實現多態。
  2. 靜態方法(無 virtual):編譯時根據變數聲明類型綁定(靜態綁定),類型轉換會改變調用目標。
  3. 重新宣告而非覆寫:子類聲明同名方法但無 override,屬於「隱藏」,不影響父類虛擬方法表。
  4. inherited:在 override 方法中呼叫 inherited 可執行父類實現,省略參數表時自動傳遞當前參數。

常見錯誤與避坑

錯誤代碼現象修正
忘記 override以為多態實則靜態綁定子類方法必須加 override
父類無 virtual編譯錯誤「Only virtual methods can be overridden」父類方法加 virtual 或子類改用 reintroduce
建構子未 override多態創建失敗constructor Create(...); override;
解構子未 override釋放時未呼叫子類清理代碼destructor Destroy; override;

最佳實踐

  • 預設將可被子類擴展的方法標記 virtual。
  • 覆寫時務必加 override,編譯器會檢查簽名一致性。
  • 不打算多態的內部輔助方法保持靜態,效能略高。
  • 使用 sealed(Delphi 10.4+)禁止進一步覆寫:procedure Proc1; override; sealed;。

深入理解 override 與靜態綁定的差異,是編寫正確、可擴展 Delphi 物件導向代碼的關鍵。建議在代碼審查中重點檢查虛擬方法覆寫的完整性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved