stored procedimientos procedimiento objeto indirecto ejemplos ejemplo duplicar duplicado complemento almacenados almacenado delphi constructor copy-constructor

delphi - objeto - procedimientos almacenados sql ejemplos



Forma correcta de duplicar el objeto Delphi (3)

¿Cuáles son los pros y los contras de la duplicación de una instancia de objeto con el constructor o la función de instancia?

Ejemplo A:

type TMyObject = class strict private FField: integer; public constructor Create(srcObj: TMyObject); overload; //alternatively: //constructor CreateFrom(srcObj: TMyObject); property Field: integer read FField; end; constructor TMyObject.Create(srcObj: TMyObject); begin inherited Create; FField := srcObj.Field; end;

Ejemplo B:

type TMyObject = class strict private FField: integer; public function Clone: TMyObject; property Field: integer read FField; end; function TMyObject.Clone: TMyObject; begin Result := TMyObject.Create; Result.FField := FField; end;

Una gran diferencia surge de inmediato en la mente: en este último caso, el constructor Create debería ser virtual para que una jerarquía de clases que soportara Clone pueda construirse basándose en el TMyObject.

Supongamos que esto no es un problema, que TMyObject y todo lo que se basa en él está completamente bajo mi control. ¿Cuál es tu forma preferida de hacer copy constructor en Delphi? ¿Qué versión encuentras más legible? ¿Cuándo utilizarías el enfoque anterior o posterior? Discutir. :)

EDITAR: Mi principal preocupación con el primer ejemplo es que el uso es muy pesado en comparación con el segundo enfoque, es decir,

newObj := TMyObject.Create(oldObj)

vs.

newObj := oldObj.Clone;

EDIT2 o "Por qué quiero una sola línea de operación"

Estoy de acuerdo en que Assign es un enfoque razonable en la mayoría de los casos. Incluso es razonable implementar ''constructor de copia'' internamente simplemente usando assign.

Por lo general, creo esas copias cuando multiprocesamiento y paso de objetos a través de la cola de mensajes. Si la creación de objetos es rápida, por lo general paso una copia del objeto original porque eso realmente simplifica los problemas de propiedad del objeto.

IOW, prefiero escribir

Send(TMyObject.Create(obj));

o

Send(obj.Clone);

a

newObj := TMyObject.Create; newObj.Assign(obj); Send(newObj);


El primero agrega información sobre qué objeto desea crear, el segundo no. Esto se puede usar para instanciar, por ejemplo, un descendiente o un ancestro de una clase

La forma Delphi ( TPersistent ) separa la creación y la clonación:

dest := TSomeClass.Create; dest.Assign(source);

y tiene esta misma propiedad que usted elige explícitamente la clase para instanciar. Pero no necesita dos constructores, uno para uso normal y otro para clonar.

editar debido a los requisitos en línea . Puede combinarlo, por supuesto, usando las metaclases Delphi (no probadas)

type TBaseSomeObject = class; TBaseObjectClass = class of TBaseSomeObject; TBaseSomeObject = class(TPersistent) function Clone(t: TBaseObjectClass = nil): TBaseSomeObject; virtual; end; ... function TBaseSomeObject.Clone(t: TBaseObjectClass = nil): TBaseSomeObject; begin if Assigned(t) then Result := t.Create else Result := TBaseObjectClass(Self.ClassType).Create; Result.Assign(Self); end; SendObject(obj.Clone); // full clone. SendObject(obj.Clone(TDescandantObject)); // Cloned into Descendant object

Por lo demás, simplemente implemente sus operadores de assign() , y puede mezclar varias formas.

edit2

Reemplacé el código anterior con el código probado en D2009. Hay algunas dependencias de los tipos que podrían haberlo confundido, espero que sea más claro de esta manera. Por supuesto, tendrás que estudiar el mecanismo de asignación. También probé el parámetro predeterminado metaclass=nil y funciona, así que lo agregué.


Me gusta el estilo de clonación , pero solo en Java (o en cualquier otro lenguaje de GC). Lo usé algunas veces en Delphi, pero sobre todo me quedo con Create y Assign , porque está mucho más claro quién es responsable de la destrucción del objeto.


No creo que exista una forma correcta de que solo dependa del estilo personal. (Y como señaló Marco, hay más formas).

  • La forma del constructor es corta, pero viola el principio de que el constructor solo debe construir el objeto. Lo cual posiblemente no sea un problema.
  • El modo clon es corto, aunque debe proporcionar una llamada para cada clase.
  • La forma de asignar es más como Delphi. Separa la creación y la inicialización, lo que es bueno porque nos gusta el método de un concepto de función que hace que el código sea mejor de mantener.

Y si implementa Assign usando streams, solo tiene un lugar donde preocuparse sobre qué campos deben estar disponibles.