재정의
다른 레코드 변수를 재정의하는 레코드 변수 선언
이미 다른 레코드 변수에 지정된 메모리
영역을 재정의하는
레코드 변수를 선언할 수 있습니다. 예를 들면,
다음
예제와 같이 검색된 데이터의 구조가
그 다음
검색에서 다른 경우에도 직렬 파일에서 데이터 영역을 차례로 읽는
루프를 작성할 수 있습니다.
Record RecordA type SerialRecord
{ fileName = "myFile" }
record_type char(1);
field1 char(20);
end
Record RecordB type BasicRecord
10 record_type char(1);
10 field2 bigint;
10 field3 decimal(7);
10 field4 char(8);
end
Program ProgramX type basicProgram
myRecordA RecordA;
myRecordB RecordB {redefines = myRecordA};
function main();
get next myRecordA;
while (myRecordA not endOfFile)
if (myRecordA.record_type == "A")
myFunction01(myRecordA.field1);
else
myFunction02(myRecordB.field2, myRecordB.field3, myRecordB.field4);
end get next myRecordA;
end endend
루프 내에서 함수는 다음 조치를
수행합니다.
- 나머지 데이터의 구조를 식별하는 코드가 있는지 입력 레코드의 첫 번째 필드를 검사합니다.
- 입력 레코드 또는 두 번째 기본 레코드를 사용하여 검색된 데이터의 다른 필드를 처리합니다. 두 번째 레코드는 입력 레코드와 같은 메모리 영역을 참조하지만 구조는 다릅니다.
한 레코드 변수를 다른 변수의 재정의로 선언하기 위해 redefines 특성을 사용합니다. 이 특성은 다른 레코드 변수의 이름을 승인합니다. 레코드 파트 정의가 아니라 레코드 변수 선언에서만 이 특성을 사용할 수 있습니다.
원래 레코드와 오버레이 레코드는 모든 유형의
구조화 레코드일 수 있으며
다음 제한사항이 있습니다.
- 레코드는 같은 범위에
있어야 합니다. 예를 들어, 첫 번째 레코드를
레코드를 포함하는 필드로 선언하는 경우 첫 번째
레코드를
재정의하는 레코드도 동일한 포함 레코드의 필드로 선언해야
합니다.
마찬가지로 함수 외부에서 라이브러리 내에 레코드를 선언하는 경우 다른 레코드도 함수 외부에서 동일한 라이브러리에 선언해야 합니다.Record StructuredRecordA 10 x INT; end Record StructuredRecordB 10 y INT; end Record TestRecord myRec1 StructuredRecordA; myRec2 StructuredRecordB { redefines=myRec1}; end - 오버레이 레코드의 길이는 원래 레코드보다 짧거나 같아야 합니다. 이 제한사항으로 인해 사용자 코드는 재정의 중인 메모리의 영역에 있지 않은 오버레이 레코드의 영역에 액세스할 수 없습니다.
- 일부 레코드 스테레오타입에는 숨겨진 바이트가 필요할 수 있습니다. 자세한 정보는 개별 레코드 유형의 문서를 확인하십시오.
원래 레코드에 지정하는 특성은 오버레이 레코드에 영향을 미치지 않습니다. 메모리 영역만 재정의됩니다.
입출력(I/O)에는 오버레이 레코드를 사용할 수 없습니다.
동일한 레코드에서 다른 레코드를 재정의하는 필드 선언
다음과 같은 상황에서만 redefines 특성을
필드에
적용할 수 있습니다.
- 재정의할 필드와 재정의되는 필드가 동일한 레코드에 있어야 합니다.
- 레코드가 구조화되어 있어야 합니다.
- 두 필드가 동일한 레벨에 있고 동일한 상위를 갖고 있어야 합니다.
- 재정의할 필드의 길이는 재정의되는 필드의 길이보다 길지 않아야 합니다.
두 필드의 유형은 다를 수
있지만 레코드를 전달하거나 초기화하는 경우
재정의되는 레코드의 유형만 유지됩니다. 다음
예제에서
이에 대해 설명합니다.
Record exampleRecord1
10 a INT;
20 aa INT;
20 ab CHAR(4) { redefines = a.aa };
10 b CHAR(4) { redefines = a };
end
호출 명령문에서 exampleRecord1을 기반으로 변수를 전달하는 경우 재정의되는 영역의 데이터가 CHAR(4)가 아니라 INT인 것처럼 변환됩니다. a.ab를 초기화하면(예를 들면, set empty 문 사용) 재정의되는 영역의 데이터가 공백이 아니라 2진수 0으로 설정됩니다.
재정의를
수행하는 필드는 하위 필드와 재정의를 무시하고
재정의되는 필드 바로 뒤에 와야 합니다. 다음
두
예제 모두 올바릅니다.
Record exampleRecord2
10 a int;
20 x int;
10 b char(4) { redefines = a };
20 z char(4);
10 c char(4) { redefines = a };
end
배열로 정의된 필드는 재정의되지 않을 수 있습니다.
필드의 상위 중 하나가
배열이어서 필드가 배열인 경우에는 재정의될 수 있습니다.
Record exampleRecord3
10 a int[2];
10 b char(2) { redefines = a }; // Illegal because a is an array
end
Record exampleRecord4
10 a bigint;
10 b char(1)[8] { redefines = a }; // Legal
end
Record exampleRecord5
10 top char(4)[3];
20 a int;
20 b smallint { redefines = a }; // Legal even though a is an array
end
Record exampleRecord6
10 top char(12)[5];
20 middle char(4)[3];
30 a int;
30 b smallint { redefines = a }; // Legal even though a is an array
end
다음의 상세 예제에서는 필드 재정의를 사용하여 유럽식 날짜(일이
먼저
표시됨)로 미국식 날짜(월이 먼저 표시됨)를 정규화합니다. RecC 레코드
정의에서 usBillingDate, euroBillingDate,
billingDate 셋 모두 레벨 번호가 같지만(10) usBillingDate,
euroBillingDate는 billingDate에
속하도록 작성됩니다. 들여쓰기는 레벨 번호가 같아도
세 필드
모두 동일한 공간을 점유함을 보이기 위한 시각적
단서입니다.
재정의할 필드가 항상 재정의되는 필드를 겹쳐씁니다.
package com.companyb.customer;
Record RecC type basicRecord
10 dateFormat SMALLINT;
10 billingDate CHAR(8);
10 usBillingDate CHAR(8) {redefines=billingDate};
20 month CHAR(2);
20 day CHAR(2);
20 year CHAR(4);
10 euroBillingDate CHAR(8) {redefines=billingDate};
20 day CHAR(2);
20 month CHAR(2);
20 year CHAR(4);
10 deliveryDate CHAR(8);
10 usDeliveryDate CHAR(8) {redefines=deliveryDate};
20 month CHAR(2);
20 day CHAR(2);
20 year CHAR(4);
10 euroDeliveryDate CHAR(8) {redefines=deliveryDate};
20 day CHAR(2);
20 month CHAR(2);
20 year CHAR(4);
End
program RedefinesExample type BasicProgram (
inDateFormat SMALLINT,
inDeliveryMonth CHAR(2),
inDeliveryDay CHAR(2),
inDeliveryYear CHAR(4),
inBillingMonth CHAR(2),
inBillingDay CHAR(2),
inBillingYear CHAR(4))
{alias="REDXMP3"}
// aRec is a structured record whose billingDate and deliveryDate items
// are each redefined by two other items with substructure,
// whose level is the same, and whose parent is the same
aRec RecC;
const USDateFormat SMALLINT=1;
const EURODateFormat SMALLINT=2;
function main()
aRec.dateFormat = inDateFormat;
// If date to be in US format
if ( inDateFormat == USDateFormat )
usBillingDate.month = inBillingMonth;
usBillingDate.day = inBillingDay;
usBillingDate.year = inBillingYear;
usDeliveryDate.month = inDeliveryMonth;
usDeliveryDate.day = inDeliveryDay;
usDeliveryDate.year = inDeliveryYear;
else // Date must be in European format
euroBillingDate.month = inBillingMonth;
euroBillingDate.day = inBillingDay;
euroBillingDate.year = inBillingYear;
euroDeliveryDate.month = inDeliveryMonth;
euroDeliveryDate.day = inDeliveryDay;
euroDeliveryDate.year = inDeliveryYear;
end end
end