2009-11-21 13 views
5

Tengo una clase de la mía, vamos a llamarlo TMyObject, que debe devolver una copia ligeramente modificada de sí mismo. Así, una de sus funciones debe devolver un objeto del mismo tipo que en sí:¿Puedo crear un objeto del mismo tipo que él?

function TMyObject.TrimEnds: TMyObject; 
begin 
    Result:= TMyObject.Create; 
    Result.DoStuff; 
edn; 

¿Puedo hacer eso? ¿Es legítimo lo que estoy haciendo?

Quiero decir, ya lo probé y el compilador me permite hacerlo, pero me pregunto si habrá efectos negativos a largo plazo/ocultos.

Cualquier pensamiento será apreciado. Gracias.


Editar: La nueva copia ligeramente modificada se guardará en el disco. Es una especie de 'Guardar como ...'. Cómo funciona: el objeto original crea una copia de sí mismo, ordena a esta copia que realice algunos cambios y que guarde en el disco. Luego, el original libera la copia. De esta manera, mantengo el objeto original en la memoria sin cambios, pero tengo una versión modificada de esto en el disco.

Puede pensar que mi objeto contiene una imagen. Lo que necesito es una función que devuelva una copia ligeramente modificada de la imagen.

Respuesta

5

pero me pregunto si habrá largos tiempo/efectos negativos ocultos.

No veo ninguno, y solía hacer esto con mis propias listas vinculadas, y nunca tuve ningún problema. Creo que es más o menos lo mismo que crear una instancia en cualquier otro lugar.

+0

Grande. Muchas gracias a todos. – Ampere

+0

Asegúrate de liberar recursos. De lo contrario, tus objetos permanecen en la memoria y nunca se liberan. Bueno, en la terminación del programa es. – Scoregraphic

1

no hay absolutamente nada de malo en lo que escribió. simplemente está devolviendo un objeto y esto es perfectamente válido, podría ser cualquier otro objeto de cualquier otro tipo.

2

Supongo que tienes razón, este fragmento de código me parece incorrecto. Siempre tiene que dejar en claro quién es responsable de liberando el objeto que devuelve. En la mayoría de los casos, este objeto no se liberará.

Un mejor enfoque es dejar que la persona que llama crea el objeto, pasarlo a su método (solo necesita un procedimiento) que lo modifica.

Tengo curiosidad por saber por qué querría devolver una "versión ligeramente modificada" de su objeto. Suena contra-intuitivo para mí ...

+0

Por favor, mira mi publicación original. He agregado más explicaciones. – Ampere

2

Como han dicho otros, no hay nada de malo en eso, pero puede haber formas mejores.

Variante 1: Cambie esto al método de clase y asígnele un nombre significativo.

class function TMyObject.CreateSpecialized: TMyObject; 
begin 
    Result := TMyObject.Create; 
    //initialize Result 
end; 

anObj := TMyObject.CreateSpecialized; 

Variante 2: Utilice un constructor. Puedes tener múltiples constructores en una clase.

constructor TMyObject.CreateSpecialized; 
begin 
    Create; // make sure everything is initialized correctly 
    // now do custom initialization 
end; 

anObj := TMyObject.CreateSpecialized; 

El uso es el mismo en ambos ejemplos, pero en el segundo caso, sus intenciones son más claras para un lector aleatorio.

Si desea tomar un objeto y crear otro basado en los campos del primer objeto, use un constructor con parámetro.

constructor TMyObject.CreateSpecialized(obj: TMyObject); 
begin 
    Create; 
    intField := obj.IntField * 2; 
end; 

anObj := TMyObject.CreateSpecialized(otherObj); 
+0

+1 para el método de clase – RRUZ

+0

Existe cierta tradición en llamar a su último ejemplo un "constructor de copia" –

+0

@PA: No, ya que un constructor de copia crearía una * copia * idéntica, no mutada. Los constructores de copia no se usan mucho en Delphi. Como a todos los objetos se accede únicamente a través de referencias, rara vez se necesitan. – mghie

2

Si usted tiene una nueva clase derivada de TMyObject como TMyOtherObject = class(TMyObject), la función TrimEnds todavía devolverá un TMyObject en lugar de un TMyOtherObject como uno podría esperar.

Puede solucionar este problema mediante el uso de este esquema:

TMyObjectClass = class of TMyObject; 

function TMyObject.TrimEnds: TMyObject; 
begin 
    Result:= TMyObjectClass(ClassType).Create; 
    Result.DoStuff; 
end; 
+0

¿No sería necesario que Create sea virtual? – gabr

+0

@gabr: Solo cuando la clase derivada tiene su propia creación. En ese caso, la base Create debe ser virtual y la derivada debe anularla. El uso de ClassType solo garantiza que se crea una instancia de la clase correcta: el usuario debe tener cuidado de llamar al Create correcto. –

+0

El constructor debe declararse virtual, de lo contrario el código del constructor no se ejecutará: http://stackoverflow.com/questions/791069/ – mjn

Cuestiones relacionadas