Pascal/FPC is 型別判斷、as 安全轉型、TClass(X) 裸強制轉換
is 與 as 的使用方式
1 is 運算子:執行期型別偵測
判斷物件實體是否屬於指定類別或其子類別,回傳布林值 True/False,做為安全前置檢核使用。
2 as 運算子:安全型別轉換
以執行期型別驗證為基礎的向上/向下轉型;若型別不相符則直接拋出例外,優先保障執行安全。
3 TMyClass(X) 裸強制轉換(未檢核轉型)
不執行執行期檢核,直接強制重新解讀記憶體;執行速度更快,但當型別不匹配時會產生未定義行為(程式崩潰、呼叫錯誤方法、記憶體錯誤),僅可在透過 is 確認型別後使用。
program Demo;
{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
{$codepage utf8}
uses
SysUtils;
type
// 基礎類別
TFather = class
procedure FatherMethod;
end;
// 衍生類別,繼承 TFather
TSon = class(TFather)
procedure SonMethod;
end;
procedure TFather.FatherMethod;
begin
WriteLn('FatherMethod');
end;
procedure TSon.SonMethod;
begin
WriteLn('SonMethod');
end;
var
Son: TSon;
C: TFather; // 基礎類別參考變數
begin
Son := TSon.Create;
try
// 衍生類別實體可直接呼叫所有方法
Son.FatherMethod;
Son.SonMethod;
// 向上轉型:將衍生類別指派給基礎類別參考,語法合法
C := Son;
C.FatherMethod; // 基礎類別參考可呼叫自身擁有的方法
// C.SonMethod; // 編譯錯誤:TFather 不存在此方法
// 1. is 型別判斷 + as 安全轉換
if C is TSon then
(C as TSon).SonMethod;
finally
FreeAndNil(Son);
end;
end.Code language: JavaScript (javascript)
執行結果
FatherMethod
SonMethod
FatherMethod
SonMethod

C 原本是 TFather 型別的參考變數 C: TFather;,但實際指向的物件為 C := Son;,子類別實體可透過該參考呼叫父類別方法 C.FatherMethod;,
若要呼叫子類別專屬方法 (C as TSon).SonMethod; ,必須先透過 is 進行型別判斷 if C is TSon then,避免執行時發生錯誤。
as 與 TFather(X) 轉換方式對照
1. X as TFather
安全轉型,建議一般場景使用
- 底層自動執行執行期型別檢核,等同隱式先行執行
X is TMyClass; - 型別不匹配時拋出
EInvalidCast例外,程式可攔截處理錯誤; - 會產生輕微效能開銷,多數業務程式可忽略不計。
2. TFather(X) 強制裸轉換
無檢核直接轉型,僅適用高效能需求場景,暴力強制轉換記憶體解讀。
- 完全跳過執行期型別檢查,直接強制解讀物件指標;
- 執行速度略快;
- 風險:若
X實體並非目標類別,呼叫方法會造成記憶體越界、堆疊崩潰、隨機例外(未定義行為); - 僅允許搭配前置
is判斷後使用,確保型別一定相符:
// 安全寫法1:as 轉換(通用)
if A is TFather then
(A as TFather).CallSomeMethodOfFather;
// 安全寫法2:裸強制轉換(極致效能,已前置is檢核)
if A is TFather then
TMyClass(A).CallSomeMethodOfMyClass;Code language: JavaScript (javascript)
Previous: 建構函式與解構函式
Next: 屬性(Property)