Delphi 物件導向程式設計的核心在於類的成員設計。本文系統梳理類字段、靜態字段、方法綁定、虛擬/動態方法、類方法、建構子/解構子、屬性與運算子重載等關鍵概念,並附上可編譯的代碼片段供實戰參考。
type
TAncestor = class
Value: Integer;
end;
TDescendant = class(TAncestor)
Value: string; // 遮蔽繼承的 Value 字段
end;
var
MyObject: TAncestor;
begin
MyObject := TDescendant.Create;
// MyObject.Value := 'Hello!'; // 編譯錯誤:TAncestor.Value 是 Integer
(MyObject as TDescendant).Value := 'Hello!'; // 正確:類型轉換後存取子類字段
end;
重點:同名字段在子類中會遮蔽父類字段,需透過類型轉換存取具體類型的字段。
type
TMyClass = class
public
class var
Red, Green, Blue: Integer; // 類靜態字段
var
InstanceField: Integer; // 實例字段
end;
// 透過類名直接存取
TMyClass.Red := 1;
TMyClass.Green := 2;
TMyClass.Blue := 3;
// 也可透過實例存取(編譯器自動轉為類存取)
var
Obj: TMyClass;
begin
Obj := TMyClass.Create;
Obj.Red := 10; // 實際操作 TMyClass.Red
end;
type
TFigure = class
procedure Draw; // 靜態
end;
TRectangle = class(TFigure)
procedure Draw; // 隱藏父類方法
end;
var
Fig: TFigure;
Rect: TRectangle;
begin
Fig := TFigure.Create; Fig.Draw; // 呼叫 TFigure.Draw
Fig := TRectangle.Create; Fig.Draw; // 仍呼叫 TFigure.Draw(靜態綁定)
TRectangle(Fig).Draw; // 透過類型轉換呼叫 TRectangle.Draw
end;
type
TFigure = class
procedure Draw; virtual; // 虛擬方法
end;
TRectangle = class(TFigure)
procedure Draw; override;
end;
TEllipse = class(TFigure)
procedure Draw; override;
end;
var
Fig: TFigure;
begin
Fig := TRectangle.Create; Fig.Draw; // 呼叫 TRectangle.Draw
Fig := TEllipse.Create; Fig.Draw; // 呼叫 TEllipse.Draw
end;
差異:virtual 使用虛擬方法表(VMT),呼叫速度快但佔用空間;dynamic 使用動態方法表(DMT),節省空間但呼叫稍慢。現代應用多用 virtual。
type
T1 = class(TObject)
procedure Act; virtual;
end;
T2 = class(T1)
procedure Act; // 未加 override,僅重新宣告
end;
var
Obj: T1;
begin
Obj := T2.Create;
Obj.Act; // 呼叫 T1.Act(非多態)
end;
type
TFigure = class
public
class function Supports(Operation: string): Boolean; virtual;
class procedure GetInfo(var Info: TFigureInfo); virtual;
end;
class procedure TFigure.GetInfo(var Info: TFigureInfo);
begin
// 實現
end;
type
TMyClass = class
strict private
class var FX: Integer;
strict protected
class function GetX: Integer; static;
class procedure SetX(val: Integer); static;
public
class property X: Integer read GetX write SetX;
class procedure StatProc(s: String); static;
end;
// 呼叫
TMyClass.X := 17;
TMyClass.StatProc('Hello');
type
T1 = class(TObject)
procedure Test(I: Integer); overload; virtual;
end;
T2 = class(T1)
procedure Test(S: string); reintroduce; overload; // 重新引入並重載
end;
var
Obj: T1;
begin
Obj := T2.Create;
Obj.Test('Hello!'); // 呼叫 T2.Test(string)
Obj.Test(7); // 呼叫 T1.Test(Integer)
end;
type
TShape = class(TGraphicControl)
private
FPen: TPen;
FBrush: TBrush;
procedure PenChanged(Sender: TObject);
procedure BrushChanged(Sender: TObject);
public
constructor Create(Owner: TComponent); override;
destructor Destroy; override;
end;
constructor TShape.Create(Owner: TComponent);
begin
inherited Create(Owner); // 初始化繼承部分
Width := 65; Height := 65; // 修改繼承屬性
FPen := TPen.Create; // 初始化新字段
FPen.OnChange := PenChanged;
FBrush := TBrush.Create;
FBrush.OnChange := BrushChanged;
end;
destructor TShape.Destroy;
begin
FPen.Free;
FBrush.Free;
inherited Destroy;
end;
最佳實踐:
inherited Create,再初始化自身資源。inherited Destroy。override 確保多態銷毀。| 成員類型 | 關鍵字 | 多態性 | 存取方式 | 典型用途 |
|---|---|---|---|---|
| 實例字段 | var | 否 | 實例 | 物件狀態 |
| 靜態字段 | class var | 否 | 類名/實例 | 共享資料、計數器 |
| 靜態方法 | (無) | 否 | 類名/實例 | 工具函數 |
| 虛擬方法 | virtual/override | 是 | 實例 | 核心多態行為 |
| 動態方法 | dynamic/override | 是 | 實例 | 大量方法節省空間 |
| 類方法 | class procedure/function | 是 | 類名/實例 | 工廠、單例、註冊 |
| 靜態類方法 | class ... static | 否 | 類名 | 類屬性存取器 |
| 建構子 | constructor | 是 | 類名 | 初始化 |
| 解構子 | destructor | 是 | 實例 | 清理資源 |
熟練掌握各類成員的語義與綁定規則,能讓 Delphi 類設計更清晰、擴展性更強,避免常見的「以為多態實則靜態綁定」等陷阱。