Наследование и виртуальные методы

Наследование, виртуальные методы, override, reintroduce

Пример наследования классов

Object Pascal поддерживает наследование и виртуальные методы. В примере ниже класс TDog наследует TAnimal:

TDog — подкласс (производный класс), TAnimal — родительский класс (базовый класс)

program AnimalDemo;
{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
{$codepage utf8}
uses SysUtils;

type
  // Родительский класс животных
  TAnimal = class
    procedure Cry; virtual; // Виртуальный метод: звук животного
  end; // Конец определения класса, только end;

  // Подкласс Собака, наследует Animal и переопределяет звук
  TDog = class(TAnimal)
    procedure Cry; override;
  end;

procedure TAnimal.Cry;
begin
  WriteLn('Животное издает звук');
end;

procedure TDog.Cry;
begin
  WriteLn('Гав гав гав');
end;

var
  Pet: TAnimal;
begin
  // Экземпляр родительского класса
  Pet := TAnimal.Create;
  try
    Pet.Cry;
  finally
    FreeAndNil(Pet);
  end;

  // Экземпляр подкласса в переменной родительского класса, полиморфизм работает
  Pet := TDog.Create;
  try
    Pet.Cry;
  finally
    FreeAndNil(Pet);
  end;
end.Code language: JavaScript (javascript)

Результат выполнения

D:\fpcdemo>fpc mydemo.dpr
Free Pascal Compiler version 3.2.2 [2021/05/15] for i386
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling mydemo.dpr
Linking mydemo.exe
45 lines compiled, 0.1 sec, 68544 bytes code, 4260 bytes data

D:\fpcdemo>mydemo
Животное издает звук
Гав гав гавCode language: CSS (css)

FreeAndNil

Безопасное освобождение объекта, объединяет два действия:

  1. Вызов метода Free объекта для очистки памяти;
  2. Присвоить переменной значение nil, чтобы избежать висячих указателей.

В коде выше объект подкласса TDog хранится в переменной Pet типа TAnimal. При вызове метода Cry через Pet выполняется реализация из TDog, а не из TAnimal — это полиморфизм.

  • Cry; virtual помечает родительский метод как виртуальный, включая полиморфизм во время выполнения;
  • Подкласс переопределяет метод Cry с помощью ключевого слова override;
  • Переменная объявлена как TAnimal, но содержит реальный объект TDog, поэтому автоматически запускается лай собаки.

Для методов с модификатором virtual: компилятор подбирает нужную реализацию во время выполнения по реальному типу объекта.

Если убрать модификаторы virtual и override

Оба вызова будут запускать метод родительского класса

На изображении выше показан результат после удаления virtual и override

Весь вывод берется из реализации класса TAnimal

Компилятор учитывает только объявленный тип переменной TMyClass и игнорирует реальный тип объекта во время выполнения.

  • Обычные методы по умолчанию не виртуальные, они становятся виртуальными только с модификатором virtual;
  • При переопределении унаследованного виртуального метода в подклассе обязательно используйте override, иначе компилятор выдаст предупреждение;
  • Используйте reintroduce, если нужно скрыть одноименный виртуальный метод родителя без переопределения (не рекомендуется, вызывает путаницу), аналог ключевого слова new в C#

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

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