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)