Yuha 님이 쓰신 글 :
: 구글링 해도 비슷한 답이 나오지 않네요.
:
: type
: TKind = packed record
: a: string;
: b: integer;
: end;
:
: 위 처럼 record type 선언을 하고 java 의 extends 처럼 하나의 record 로 만들고자 합니다.
:
: type
: TKindAll = packed reocrd
: TKind;
:
: c:integer;
: d: string;
: end;
:
: 이렇게 추가하는 방법이 있을까요?
:
: 사용시
: KindAll.TKind.~ 방식이 아닌 KindAll.a 와 같이 사용될 수 있으면 합니다.
답변:
C++ 언어에선 다음과 같이... 익명의 구조체를 정의해서 사용할 수 있지만
struct TypeKindAll
{
// TypeKind
struct {
std::string s;
int b;
};
int k;
};
void __fastcall TForm2::Button2Click(TObject *Sender)
{
TypeKindAll All;
All.s = "123";
}
델파이 파스칼 언어는 anonymous 레코드 정의를 지원하지 않으므로 불가능 하고.
파스칼에서 익명이 가능하도록 하려면 레코드 Variant 구조를 (C++에서 union 구조) 이용해야 하는데...
Tx = record
a: Integer;
s: string;
과 같이 레코드에 string 타입이 정의되어 있으면 레코드 Variant 구조를 이용하는 것도
델파이 파스칼 언어로는 불가능 합니다.
왜냐면...
string 타입은 레퍼런스 카운트를 유지하기 위해 컴파일러가 내부적으로 InitializeRecord(), FinalizeRecord()
RTL Internal 함수를 호출하는 코드를 생성하기 때문이죠.
레코드 Variant 구조(union)에선 다른 필드와 메모리가 겹쳐서 사용되므로 컴파일러가 에러를 내버립니다.
그뿐만 아니라 매니지드 레코드를 지원한답시고 사용자 의도와 상관없이 델파이 컴파일러가 내부적으로
try... finally 블럭을 Implicit로 생성하므로 레코드 Variant 구조를 이용하는 것도 불가능 하고.
사실상 델파이에서 새로 도입된 Managed Record는 언어적 진보라기 보다는 컴파일러 꼼수에 불과 함.
결국...
Create 컨스트럭터를 호출해서 힙에 생성해서 사용해야 하는 방법이 아닌 레코드와 같은 시멘틱 룰을 적용하는 방법으로
구현하기 위해선 다음과 같이 object 키워드를 이용하는 꼼수를 사용해야 합니다.
type
TKind = object
a: string;
b: Integer;
end;
TKindAll = object(TKind)
k: Integer;
end;
procedure TForm3.Button1Click(Sender: TObject);
var
r: TKindAll;
begin
r := Default(TKindAll);
r.a := 'abc';
end;
object는 class와 달리 힙 생성이 필요없고, 스택에 사이즈 만큼 영역을 차지하게 됍니다.
object 시멘틱 룰을 확장해서 컴파일러 구조를 잡지않고, class 키워드를 도입해서 시멘틱 룰을 한정시켜 버리는 바람에
RAII 패턴도 쓸수 없는 컴파일러로 언어를 망가뜨려 버렸지요.