2009-07-12 7 views
17

Entonces, ¿cuál será la forma preferida de inicializar registros?Delphi: Generador de registros frente a la función de fábrica

Con una 'función de fábrica':

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; 

o un constructor:

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; 

siento que las cosas constructor más encapsulados, pero hace que sea fácil confundirse al leer el código. Lo hace parecer una clase que no tiene una llamada gratuita. También es más para escribir ...

¿Por qué preferirías una sobre la otra?

Respuesta

11

Prefiero las clases, pero si tengo que usar registros, me gusta tratarlos de la manera más similar posible. Entonces uso el constructor de registros.

Pero hay un error molesto con los registros y unidades. Si una función devuelve un registro (con métodos), produce un error interno si desea acceder a estos métodos. Puede eludir esto asignándolo a otra variable:

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

También uso constructores de registros. Puedes nombrar algo diferente de "Crear" si lo deseas, para que sepas que es un registro. –

+5

FYI El problema de error interno que ha mencionado parece haberse solucionado en D2010. –

+1

La pregunta es sobre el constructor, no solo un método. Si seguimos la misma notación para el constructor, es difícil de entender a partir del código si es un registro o instancia de clase. Para la clase, significa pérdida de memoria, por lo que cualquier persona que vea ese código deberá verificar si realmente es un registro o una clase. Entonces creo que es una mala manera. –

0

Normalmente no creo constructores para los registros. No es compatible con todas las versiones (y FPC). Además, por lo general, se usan solo en un lugar y, a menudo, un fillchar es suficiente.

+4

Es un poco difícil de usar FillChar() para inicializar un registro con valores, ¿no es así? – Vegar

1

En un proyecto Delphi que creé, utilicé registros en lugar de clases para reducir la cantidad de sobrecarga en una lista. Tendría varios cientos de registros en una matriz dinámica, así que creé dos registros. El primer registro fue para el artículo en sí. Los campos se hicieron privados (sí, puede usar registros privados/protegidos con registros) y agregó propiedades de solo lectura a la sección pública. También se agregó un constructor adicional para inicializar el registro de la manera correcta. Esta configuración me permitió proteger los contenidos de este registro de otros desarrolladores. El segundo registro era simplemente un contenedor alrededor de una matriz dinámica del tipo de registro anterior. La matriz sería privada y agregué métodos para obtener, agregar y eliminar registros en esta lista. Como resultado, toda la lista está protegida contra el mal uso por parte de otros desarrolladores y también tiene una carga mucho menor que una solución TList/TObjectList regular.

Tenga en cuenta que los registros no son clases. No puede heredar constructores y otros métodos. Tienen menos funcionalidad que las clases reales en entornos WIN32. En .NET, simplemente se promocionan a clases nuevamente. Y no es muy útil agregar un constructor cuando los desarrolladores pueden modificar fácilmente el contenido de cada campo de su registro. Deberías usar constructores para proteger esos campos en su lugar.

2

preferiría "método de fábrica" ​​como

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

función de fábrica independiente Fugas de encapsulado y registrar los constructores simplemente confunden en mi humilde opinión.

Cuestiones relacionadas