Итог по 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, чтобы избежать ошибок во время выполнения.

Сравнение преобразований 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)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *