2009-07-12 10 views
17

레코드를 초기화하는 기본 방법은 무엇입니까? 는 '공장 기능'으로Delphi : 레코드 생성자 대 팩토리 함수

:

TMyRecord = record 
    valueX: integer; 
    valueY: integer; 
end; 

function MyRecord(const AValueX, AValueY: integer): TMyRecord; 
begin 
    result.valueX := AValueX; 
    result.valueY := AValueY; 
end; 

var 
    myrec: TMyRecord; 
begin 
    myrec := MyRecord(1, 2); 
end; 

또는 생성자 :

TMyRecord = record 
    valueX: integer; 
    valueY: integer; 
    constructor Create(const AValueX, AValueY: integer); 
end; 

constructor TMyRecord.Create(const AValueX, AValueY: integer); 
begin 
    self.valueX := AValueX; 
    self.valueY := AValueY; 
end; 

var 
    myrec: TMyRecord; 
begin 
    myrec := TMyRecord.Create(1, 2); 
end; 

내가 생성자 일을 더 캡슐화 있다고 생각하지만, 코드를 읽을 때 쉽게 혼동 할 수 있습니다. 그것은 무료 전화가없는 수업처럼 보이게합니다. 입력하는 것이 더 많습니다 ...

왜 다른 것을 선호합니까?

답변

11

필자는 클래스를 선호하지만 레코드를 사용해야하는 경우 가능한 한 클래스와 비슷하게 처리합니다. 그래서 레코드 생성자를 사용합니다.

그러나 기록과 단위에는 성가신 버그가 있습니다. 함수가 메서드를 사용하여 레코드를 반환하면 이러한 메서드에 액세스하려는 경우 내부 오류가 발생합니다. 이것을 다른 변수에 할당함으로써 우회 할 수 있습니다 :

type 
    TMyRec = record 
    .. 
    procedure X; 
    end; 


function GetRec: TMyRec; 



procedure Test; 
var 
    r1, r2 : TMyRec; 
begin 
    r1 := GetRec; 
    r1.X; // internal error 
    r2 := r1; 
    r2.X; // No internal error; 
+4

또한 레코드 생성자를 사용합니다. 원하는 경우 "작성"과 다른 이름을 지정할 수 있으므로 레코드라는 것을 알 수 있습니다. –

+5

FYI 언급 한 내부 오류 문제가 D2010에서 수정 된 것으로 보입니다. –

+1

질문은 단지 방법이 아니라 생성자에 관한 것입니다. 생성자에 대해 동일한 표기법을 따르는 경우 레코드가 클래스인지 인스턴스인지를 코드에서 이해하기가 어렵습니다. 클래스의 경우 메모리 누수를 의미하므로 코드를 본 사람은 실제로 레코드 또는 클래스인지 확인해야합니다. 그래서 나는 그것이 나쁜 길이다라고 생각한다. –

0

나는 보통 레코드 용 생성자를 만들지 않습니다. 모든 버전 (및 FPC)과 호환되지 않습니다. 또한 일반적으로 한 곳에서만 사용되며 자주 fillchar이면 충분합니다.

+4

FillChar()를 사용하여 값으로 레코드를 초기화하는 것은 약간 어렵습니다. 그렇지 않습니까? – Vegar

1

필자가 만든 Delphi 프로젝트에서 필자는 클래스 대신 레코드를 사용하여 목록의 오버 헤드를 줄였습니다. 동적 배열에 수백 개의 레코드가 있으므로 두 레코드를 만들었습니다. 첫 번째 레코드는 항목 자체에 대한 레코드입니다. 필드는 비공개로 설정되었으므로 (예, 레코드를 사용하여 개인/보호를 사용할 수 있음) 공용 섹션에 읽기 전용 속성을 추가했습니다. 추가 생성자를 추가하여 올바른 방식으로 레코드를 초기화했습니다. 이 설정을 통해 다른 개발자로부터이 레코드의 내용을 보호 할 수있었습니다. 두 번째 레코드는 이전 레코드 유형의 동적 배열을 둘러싼 래퍼입니다. 배열은 비공개이고이 목록의 레코드를 가져오고 추가하고 삭제하는 메서드를 추가했습니다. 결과적으로 전체 목록은 다른 개발자의 오용으로부터 보호되며 일반 TList/TObjectList 솔루션보다 오버 헤드가 훨씬 적습니다.

레코드가 클래스가 아닙니다. 생성자와 다른 메소드를 상속받을 수는 없습니다. WIN32 환경에서 실제 클래스보다 기능이 적습니다. .NET에서는 클래스로 다시 승격됩니다. 개발자가 레코드의 각 필드의 내용을 쉽게 수정할 수있을 때 생성자 추가 기능을 사용하는 것은 그리 유용하지 않습니다. 대신 해당 필드를 보호하기 위해 생성자를 사용해야합니다.

2

내가

function TMyRecord.CreateRec(const AValueX, AValueY: integer): TMyRecord; 

별도의 공장 기능처럼 "팩토리 메소드"를 원합니다는 incapsulation 기록 생성자 그냥 이럴 혼동 누수.