정의 — 확장 레코드(Extended Record)란
정의 — 확장 레코드(Extended Record)란
확장 레코드는 여러 면에서 객체(object)와 동등하고, 덜하지만 클래스와도 동등해요. 즉 레코드에 메서드와 프로퍼티가 결합된 형태예요. 객체처럼 변수로 정의되면 스택에 할당되고, 생성자가 필요 없어요. 다만 상속과 다형성을 허용하지 않는다는 한계가 있어요. 레코드의 하위 레코드를 만들 수는 없어요[^1].
본문
그렇다면 왜 확장 레코드를 도입했을까요? Delphi 2005가 .NET에 도입된 기능 중 하나를 지원하기 위해 도입했어요. Delphi는 옛 TP 스타일의 객체를 폐기하고 .NET의 기능을 확장 레코드로 재도입했죠. Free Pascal은 Delphi 호환을 목표로 하므로 확장 레코드를 Free Pascal에서도 허용하는데, Delphi 모드에서만 허용해요.
ObjFPC 모드에서 확장 레코드를 쓰고 싶으면 모드 스위치를 사용해야 해요.
{$mode objfpc}
{$modeswitch advancedrecords}
호환성만이 확장 레코드를 도입한 이유는 아니에요. 레코드에 메서드나 프로퍼티를 쓰는 데는 실용적인 이유가 있어요.
- 객체 지향적 프로그래밍 접근 방식에 더 부합해요. 타입이 그 타입에서 동작하는 메서드도 함께 포함하니까요.
- 절차적 접근 방식과 달리, 레코드에서 동작하는 모든 연산을 레코드 안에 넣으면 IDE가 코드 완성 옵션을 표시할 때 레코드에서 사용 가능한 메서드를 보여줄 수 있어요.
확장 레코드를 정의하는 것은 객체나 클래스를 정의하는 것과 아주 비슷해요. 문법 다이어그램은 문서를 참고하세요. 클래스나 객체와 비교했을 때 제약이 문법 다이어그램에서 명확히 드러나요.
- 레코드의 상속은 없어요.
- published, protected 섹션은 존재하지 않아요.
- 생성자나 소멸자를 정의할 수 없어요.
- 클래스 메서드(그렇게 부를 수 있다면)는
static키워드가 필요해요. - 메서드는 virtual이나 abstract일 수 없어요 — 상속이 없다는 사실의 자연스러운 결과예요.
그 외에는 정의가 클래스나 객체와 매우 유사하고, 확장 레코드에 연산자를 정의할 수 있다는 점만 다르다.
Remark 변형 레코드(variant record)의 경우
Case키워드가 암시적으로var섹션을 시작해요. 즉 변형 부분에는 클래스 변수나 메서드가 허용되지 않아요.
유효한 확장 레코드 정의 몇 가지를 볼게요.
TTest1 = record
a : integer;
function Test(aRecurse: Boolean): Integer;
end;
TTest2 = record
private
A,b : integer;
public
procedure setA(AValue : integer);
property SafeA : Integer Read A Write SetA;
end;
TTest3 = packed record
private
fA,fb : byte;
procedure setA(AValue : Integer);
function geta : integer;
public
property A : Integer Read GetA Write SetA;
end;
TTest4 = record
private
a : Integer;
protected
function getp : integer;
public
b : string;
procedure setp (aValue : integer);
property p : integer read Getp Write SetP;
public
case x : integer of
1 : (Q : string[10]);
2 : (S : String[10]);
end;
레코드 멤버에 가시성(visibility)을 지정할 수 있다는 점을 눈여겨보세요. 예를 들어 C 라이브러리에 대한 인터페이스를 만들 때 특히 유용해요. 실제 필드는 숨기고, 실제 필드처럼 동작하는 더 "파스칼다운" 프로퍼티를 노출할 수 있으니까요. TTest3 정의는 packed 지시자가 확장 레코드에서도 사용될 수 있음을 보여줘요. 확장 레코드는 일반 레코드와 동일한 메모리 레이아웃을 가져요. 메서드와 프로퍼티는 메모리상의 레코드 구조의 일부가 아니에요.
TTest4 정의는 확장 레코드가 여전히 변형 부분을 정의할 수 있음을 보여줘요. 일반 레코드와 마찬가지로 변형 부분은 마지막에 와야 하고, 메서드를 포함할 수 없어요.
[^1]: 레코드 헬퍼를 사용해 확장할 수는 있지만, 이에 대한 자세한 내용은 레코드 헬퍼에 관한 장에서 다뤄요.
더 알아보기
- 확장 레코드에 열거자를 붙이는 방법은 Extended record enumerators를 참고하세요
- 확장 레코드의 연산자는 Record operators에서 다뤄요