본문 바로가기
delphi

Virtual과 Override에 대한 깊이 있는 이해

by doran365 2024. 7. 31.

Virtual과 Override의 역할

Virtual 지시어의 역할

델파이는 다형성을 지원하기 위해 세 가지 지시어(virtual, dynamic, override)를 가지고 있습니다. 다형성은 런타임 시에 객체의 메소드를 호출할 때, 여러 개의 각기 다른 클래스의 인스턴스 중에서 하나를 선택할 수 있는 기능을 의미합니다. 이는 프로그램 실행 시 동적으로 객체가 결정될 수 있음을 의미합니다.

Override 지시어의 필요성

C++에서는 virtual 지시어를 반복 사용하여 메소드를 재선언할 수 있지만, 델파이에서는 override 지시어를 사용하여 이를 명확히 구분합니다. 델파이는 두 개의 키워드(virtual, override)를 통해 이러한 상황을 구분합니다.

다형성의 구현

배열을 통한 다형성 구현

다음 예제는 다형성을 어떻게 구현하는지를 보여줍니다:

var 
  Cars: array[1..2] of TCar;
begin
  Cars[1] := TCar.Create;
  Cars[2] := TRacingCar.Create;
  Cars[1].Drive;
  Cars[2].Drive;
  Cars[1].Free;
  Cars[2].Free;
end;

두 개의 TCar 객체는 배열로 선언되어 있으며, 배열의 요소로는 TCar로부터 상속된 다양한 객체들이 할당될 수 있습니다. 컴파일러는 런타임 시에 이러한 객체들의 적합한 코드를 찾아 호출해야 합니다.

Virtual과 Override의 내부 동작

Late Binding과 Early Binding

런타임까지 대기하다가 실행할 것을 찾는 것을 late binding이라고 하며, 컴파일 시에 실행할 것을 결정하는 것을 early binding이라고 합니다. late binding은 델파이와 C++에서 virtual method tables(VMTs)라는 도구를 사용하여 구현됩니다.

VMT의 역할

각 클래스는 컴파일러에 의해 생성된 하나의 VMT를 가지고 있으며, 이는 해당 클래스의 모든 virtual 메소드들의 주소를 포함합니다. virtual 지시어를 추가하면 VMT에 새로운 엔트리를 추가하고, override 지시어를 사용하면 VMT의 엔트리를 수정합니다.

Dynamic 지시어

Dynamic 지시어의 특징

Dynamic은 virtual 지시어 대신 사용할 수 있으며, dynamic method table (DMT)에 엔트리를 추가합니다. DMT는 VMT와 유사하지만, 각 클래스에서 선언한 dynamic 메소드들에 대한 엔트리만 저장합니다. 이는 메모리를 절약하는 대신, 퍼포먼스의 저하를 초래할 수 있습니다.

메시지 핸들러와 Dynamic 지시어

델파이의 메시지 핸들러는 주로 dynamic 메소드로 구현됩니다. DMT는 해당 클래스 자신의 메시지 핸들러만을 저장하기 때문에 메모리를 절약할 수 있습니다.

Override 지시어의 중요성

확장 클래스와의 호환성

Override 지시어의 추가는 앞으로 확장 클래스가 제공될 수 있음을 의미합니다. 이는 기본 클래스들의 메소드에 virtual 지시어를 지정함으로써 제품의 버전 사이에 호환성을 유지하는 데 도움을 줍니다.

버전 업데이트 시의 호환성 문제 해결

델파이의 차기 버전이 나올 때, 사용자의 컴퍼넌트 클래스가 수정해야 할 작업이 줄어들어 호환성을 유지할 수 있습니다.

요약

Virtual, dynamic, override 지시어의 사용은 다형성을 구현하고 유지하는 데 중요한 역할을 합니다. 각 지시어는 특정 상황에서 유리하게 사용할 수 있으며, 이들의 조합을 통해 보다 유연하고 확장 가능한 코드를 작성할 수 있습니다.