2009-07-12 30 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)と互換性がありません。さらに、典型的には、それらは1つの場所でのみ使用され、しばしばfillcharで十分です。

+4

FillChar()を使用してレコードを値で初期化するのは少し難しいですか? – Vegar

1

私が作成したDelphiプロジェクトでは、クラスの代わりにレコードを使用して、リストのオーバーヘッドを減らしました。私は2つのレコードを作成したので、ダイナミックな配列には何百ものレコードがあります。 最初のレコードはアイテムそのものでした。フィールドはプライベートにしました(はい、プライベート/レコードの保護を使用できます)。パブリックセクションに読み取り専用のプロパティを追加しました。追加のコンストラクタも追加され、レコードを正しい方法で初期化しました。この設定により、このレコードの内容を他の開発者から保護することができました。 2番目のレコードは、前のレコードタイプの動的配列のまわりのラッパーでした。配列はプライベートなので、このリストのレコードを取得、追加、削除するメソッドを追加しました。その結果、リスト全体が他の開発者による誤使用から保護され、通常のTList/TObjectListソリューションよりもオーバーヘッドが大幅に少なくなります。

レコードはクラスではないことに注意してください。コンストラクタやその他のメソッドを継承することはできません。 WIN32環境では、実際のクラスよりも機能が劣ります。 .NETでは、それらは再びクラスに昇格しました。 開発者がレコードの各フィールドの内容を簡単に変更できる場合は、コンストラクタの追加を使用することはあまり役に立ちません。これらのフィールドを保護するには、コンストラクタを使用する必要があります。

2

私は

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

別々のファクトリ関数のように「ファクトリメソッド」を好むがincapsulationとレコードコンストラクタはただ私見を混同リークが発生します。

関連する問題