is と as まとめ

Pascal/FPC is 型判定、as 安全キャスト、TClass(X) 検証なし強制キャスト

is と as の使い方

1 is 演算子:実行時型検出

オブジェクトインスタンスが指定クラスまたはそのサブクラスに属するか判定し、真偽値 True/False を返します。事前安全チェックに使用します。

2 as 演算子:安全な型キャスト

実行時型検証に基づくアップキャスト/ダウンキャスト。型が一致しない場合即時例外を送出し、安全性を優先します。

3 TMyClass(X) 検証なし強制キャスト(unchecked typecast)

実行時チェックを行わずメモリ解釈を強制的に上書きします。実行速度は速いですが、型不一致時に未定義動作(クラッシュ、不正メソッド呼び出し、メモリエラー)が発生するため、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)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です