is和as

Pascal/FPC is 类型判断、as 安全转换、TClass(X) 强制裸转换

is 和as的使用

1 is 运算符:运行时类型检测

判断对象实例是否属于指定类 / 其子类,返回布尔值 True/False,用于安全前置校验。

2 as 运算符:安全类型转换

基于运行时类型校验的向上 / 向下转型;类型不匹配时直接抛出异常,安全优先。

3 TMyClass(X) 裸强制转换(unchecked typecast)

无运行时校验,直接强行 reinterpret 内存;速度更快,但类型不符时会出现未定义行为(崩溃、乱调用、内存错误),仅在已用 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,这样避免报错。

asTFather(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)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注