Forum > Spanish

pregunta sobre liberacion de clases

(1/3) > >>

zelda16bit:
Hola una vez mas. O:-)

Estoy en el apartado 5 del manual:
https://castle-engine.io/modern_pascal_introduction.html#_freeing_classes

Aqui vienen algunas formas de liberar una clase y me gustaria saber cual es la mejor forma y la mas adecuada.

Otra pregunta seria si yo creo una instancia de una clase en dentro de otra y quiero eliminar esa clase en un metodo con un condicional,¿como se haria?.Elimino la instancia solo en el condicional o en el condicional y en el destructor o como.

Edson:

--- Quote from: zelda16bit on June 14, 2021, 02:42:44 pm ---Aqui vienen algunas formas de liberar una clase y me gustaria saber cual es la mejor forma y la mas adecuada.

--- End quote ---

No hay una forma mejor ni más adecuada, para todos los casos. Depende de cómo manejes tus objetos.

Por ejemplo, si eres cuidadoso y solo creas y destruyes tus objetos una vez y de forma controlada; basta con que uses  el constructor Create() para crear a los objetos y llamar al destructor Destroy() para destruirlos. Esa sería la forma estándar.

En algunos esquemas, como cuando se quieren reusar variables que apuntan a objetos, puede convenir saber si un objeto se ha liberado (si se le ha aplicado un "Destroy"). Para eso se podría usar una variable auxiliar (lo que complicaría el programa), o usar la misma variable del objeto como bandera y asignarle un valor nulo (que en Pascal es NIL) cuando se ha liberado.

Pero llamar a un Destroy() , no pone a NIL la variable del objeto, por eso es que se suele hacer:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---    objeto.Destroy;  objeto := nil; 
Luego para evitar liberar objetos ya liberados, se tendría que usar:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---if A <> nil then begin  A.Destroy;  A := nil;end;
Y como eso es una tarea común, ya existe un procedimiento creado llamado FreeAndNil(). Si tienes más curiosidad sobre FreeAndNil(), puedes ver desde Lazarus, la implementación de ese procedimiento.

También se puede liberar usando objeto.Free, pero hasta donde recuerdo, es similar a Destroy().

Muchos programadores no quieren complicarse y usan a FreeAndNil() para todo. Y eso está bien, funciona. Ellos no quieren ponerse a pensar en qué caso se debe usar FreeAndNil() o Destroy().

Personalmente a mi me gusta usar Destroy() en la mayoría de casos y solo usar FreeAndNil() cuando sea necesario dejar a NIL la variable objeto.

Edson:
Otro detalle que hay que tener en cuenta es asegurar que todos los objetos creados sean liberados, para controlar correctamente la memoria usada.

Normalmente, la secuencia formal para la vida de objetos es:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---objeto := MiClase.Create();...objeto.Destroy() 
Esa sería la forma más simple y práctica. Pero en algunos casos, cuando estamos dentro de un procedimiento, y usamos instrucciones para salir del procedimiento ante casos de error, corremos el riesgo de no pasar por la parte del Destroy():


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure algun_proc();begin  objeto := MiClase.Create();  ...  if pasa_algo_malo then exit;  ...  objeto.Destroy()  //Puede no ejecutarseend; 
Para evitar ese problema es que se suele usar la estructura TRY ... FINALLY ... END:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---objeto := MiClase.Create();  //Crea al objetotry  ...  if pasa_algo_malo then exit;  ...finally   objeto.Destroy()  //Se ejecuta siempreend; 
Es por eso que esta estructura es común y vas a verla en muchos códigos. También funciona en caso en que ocurra alguna excepción dentro del bloque de TRY ... FINALLY, por eso es que es la forma más segura de liberar objetos dentro de subrutinas.

zelda16bit:
Gracias por la respuesta Edson,pero todavia tengo una duda y voy a poner un ejemplo orientativo.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type   Tenemigo = class   end;   Tjugador = class     enemigo1: Tenemigo;     procedure colision();  end;   procedure Tjugador.colision();  begin    if colisiono(self,enemigo1) then    begin       enemigo.destroy();    end;  end; 
Bien...en el ejemplo creo una clase enemigo y otra jugador,en la clase jugador creo la instancia de enemigo y en el metodo colision compruebo con un condicional si estoy colisionando con el enemigo y si es asi lo destruyo.

Podrias explicarme de una forma mas detallada cual es la forma correcta de eliminar al enemigo y liberarlo de la memoria.

Edson:
Tal vez tu ejemplo no sea muy apropiado, porque, por la forma como has definido la clase Tjugador, se entiende que "enemigo" es una parte constituyente de Tjugador, lo cual no es usual en juegos.

Si la pregunta es como destruir objetos creados dentro de objetos. Yo diría, depende cómo quieras adminstrar a los objetos hijos (qué patrón de diseño quieras implementar).

Una forma común es asociar el ciclo de vida de los objetos hijos al objeto padre, en este caso, creamos al objeto(s) hijo(s)  en el constructor y lo destruímos en el destructor:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  THijo = class  end;  TPadre = class    hijo: THijo;    constructor Create();    destructor Destroy();  end; var  padre: TPadre; constructor TPadre.Create();begin  hijo:= THijo.Create;end; destructor TPadre.Destroy();begin  hijo.Destroy;end; 
Pero si quieres crear a los objetos hijos esporádicamente, también lo puedes hacer. Si solo manejas uno, sería simple:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  THijo = class  end;  TPadre = class    hijo: THijo;    procedure CrearHijo();    procedure DestruirHijo();  end; var  padre: TPadre; procedure TPadre.CrearHijo();begin  hijo:= THijo.Create;end; procedure TPadre.DestruirHijo();begin  hijo.Destroy;end;
La idea es que siempre se llame a DestruirHijo(), si es que se ha llamado a CrearHijo(). Otra alternativa sería que en el destructor de TPadre se verifique si el atributo "hijo" apunta a un objeto, y de ser así, se llama a Destroy().

Si manejas varios objetos hijo, que se crean y se destruyen aleatoriamente, lo más común es almacenar los objetos en contenedores como arreglos o listas, de modo que cada vez que se crea un objeto se agrega al contenedor y cada vez que se destruye se elimina del contenedor. Esto es común en aplicaciones como editores gráficos o juegos.

Los contenedores favoritos para objetos serían las listas genéricas. Es un poco largo de explicar.

En cualquier caso, se debe asegurar que todos los objetos creados sean destruídos. Eso es responsabilidad del programador.

Navigation

[0] Message Index

[#] Next page

Go to full version