상속 및 가상 메서드

상속, 가상 메서드, 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;만 작성

  // 개 서브클래스, 동물 상속 후 울음소리 재정의
  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 객체를 TAnimal 타입 변수 Pet에 저장합니다. Pet으로 Cry를 호출할 때 TAnimal의 Cry가 아닌 TDog 내 Cry가 실행되는데 이것이 다형성입니다.

  • Cry; virtual 부모 메서드를 가상으로 표시해 런타임 다형성 활성화;
  • 서브클래스는 overrideCry 재정의;
  • 변수 선언 타입은 TAnimal지만 실제 객체는 TDog이므로 개 울음 메서드가 자동 실행.

virtual 표시 메서드: 컴파일러가 런타임에 객체의 실제 타입에 맞춰 해당 메서드 구현을 매칭합니다.

virtualoverride를 삭제하면

두 번의 호출 모두 부모 클래스 메서드가 실행됨

위 이미지는 virtual, override를 삭제한 후의 결과입니다

출력값이 전부 TAnimal 내 구현에서 나옴

컴파일러는 변수 선언 타입 TMyClass만 인식하고 객체 실제 런타임 타입은 무시합니다.

  • 일반 메서드는 기본적으로 비가상, virtual을 붙여야 가상 메서드가 됨;
  • 서브클래스에서 부모 가상 메서드를 재정의하려면 override 필수, 없으면 컴파일러 경고 발생;
  • 부모 동일명 가상 메서드를 가리고 재정의하지 않으려면 reintroduce 사용 (혼동 유발로 권장하지 않음), C#의 new 키워드와 동일

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다