Cita:
Empezado por ecfisa
Código Delphi [-]...
function TMiClase.Clone: TMiClase;
begin
Result:= TMiClase.Create;
Move(Self,Result,SizeOf(Self));
end;
...
Y en ella pareciera que campos, propiedades y eventos son conservados mediante la llamada a Clone. Sin embargo no sé por qué, pienso que se me está escapando algo...
|
Hola ecfisa
. Seguramente recordarás que los dos primeros parámetros de Move no son punteros a los buffers origen y destino, sino los buffers en sí (parámetros sin tipo). Es decir, de esa forma está copiando el puntero Self sobre el puntero Result (igual que una sentencia "Result := Self") y "SizeOf(Self)" devuelve el tamaño de un puntero: 4 bytes (u 8 en ejecutables de 64 bits).
Ambas direcciones de memoria pueden ser "desreferidas" (¿está bien escrito, Ñuño?
) y usar el método InstanceSize en lugar de la función SizeOf, a fin de conseguir con Move la copia que se quiere. Pero, se atraviesan algunos problemas:
- Campos (directos o indirectos) que llevan conteo de referencias, como cadenas String, interfaces, arreglos dinámicos (lo mencionado por Román).
- Sub-objetos internos que también deban ser clonados.
- Campos THandle que guardan identificadores únicos provenientes de APIs (como es el caso de los controles de la VCL).
- Campos puntero hacia estructuras particulares del objeto.
El primer punto se resuelve mediante las funciones _CopyRecord y _CopyObject (aunque ésta última parece estar incompleta y sólo llamar a _CopyRecord). Pero el resto de los puntos son quizá la razón de por qué la
clonación de bajo nivel es un tema relegado a la alquimia.
De ahí que hoy, cuando deseo realizar alguna clonación de objetos, me limito a crear un objeto de la misma clase al cual copio sólo las propiedades publicadas, disponibles mediante reflexión (RTTI), y evitando aquellas que pudieran causar algún conflicto.
Saludos.