Ver Mensaje Individual
  #11  
Antiguo 08-09-2008
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Reputación: 0
gushynet Va por buen camino
Antes que nada agradecer las respuestas ya que me han sido de gran ayuda.

Despues de una semana probando las ideas propuestas he conseguido implementar un contenedor generico pero con ciertas restricciones que no he podido quitar.

Hare un pequeño resumen de lo que he hecho:

- He implementado una clase llamada TElemento que es el tipo de objeto que aceptan o devuelven los metodos del contenedor(bueno,los que lo necesitan).

- Esta clase tiene dos metodos abstractos llamados Asignar y Comparar.

- Por otra parte tengo una clase llamada TContenedor, que es la clase base de los posibles contenedores que se implementen. Esta clase no es funcional.

- A partir de TContenedor he definido TListaSimple que implementa una lista simple enlazada en memoria dinamica.

- En el caso concreto de TListaSimple los nodos que almacena son de tipo TNodo cuya estructura consiste en tres campos:

- ID: un entero
- Elemento: TElemento
- Siguiente: puntero a elementos de tipo TNodo.

El contenedor funciona si los objetos que se quieren introducir descienden de TElemento (primera restriccion).

El proceso que sigo para añadir un elemento es el siguiente:

- creo un objeto del mismo tipo que el pasado por parametro. En este punto me ha surgido una duda:

Al González me sugirio la siguiente sintaxis:

Código Delphi [-]o2 := TClaseBase(o1.ClassType).crear(...)


pero no funciona asi que probe la referencia de la clase en lugar de la clase base:

Código Delphi [-]type TClaseBaseClass = class of TClaseBase; ...... o2 := TClaseBaseClass(o1.ClassType).crear(...)


y si funciona. Mi duda es porque funciona asi y no como me sugirio AI Gonzalez ya que encuentro mas coherente y mas intuitiva su solucion que como yo lo he hecho. Que diferencia hay entre usar TClaseBase y TClaseBaseClass?

- Despues de asignar el elemento, lo inserto en la lista dinamica en funcion del campo ID que previamente he calculado y ya esta.



La segunda restriccion es que los objetos que se quieran almacenar en el contenedor deben disponer de los metodos Asignar y Comparar de lo contrario la historia se viene abajo ya que los uso dentro del contenedor de ahi que el usuario que quiera usar el contenedor con su jerarquia de clases debe hacer que su clase base sea descendiente de TElemento que es el que tiene definido de forma abstracta estos metodos. El usuario tiene que preocuparse de implementarlos en sus clases.

Lo que busco para que el contenedor sea totalmente generico y yo ser el hombre mas feliz del mundo mundial es eliminar estas dos restricciones.

La primera restriccion se me ocurrio eliminarla haciendo que en lugar de ser TElemento la clase base para que el contenedor funcione fuese TObject, pero me encontre con el problema de que ni Asignar ni Comparar estan definidos en TObject con lo que tampoco pude eliminar la segunda restriccion.

Supongo que no puedo redefinir la clase TObject añadiendole Asignar y Comparar como metodos abstractos, porque significaria que tendria que dar por sentado que el programador que use mi contenedor tiene redefinido en su aplicacion la clase TObject con los metodos abstractos mencionados cosa que no tendria por que saber ni hacer para poder usar el contenedor.

Y en este punto me he quedado. Al fin y al cabo lo que busco es solucionarle la papeleta al programador y que tenga que saber lo minimo sobre el contenedor para usarlo, y creo que el hecho de que el usuario del contenedor tenga que redefinir los metodos Asignar y Comparar ademas de hacer que sus clases base desciendan de TElemento hace que el objetivo que busco se quede por el camino, para mi gusto son muchas las cosas que tiene que conocer el usuario para usar el contenedor.


Una duda mas:

Sea la siguiente funcion:

Código Delphi [-]function TListaSimple.Actual():TElemento var E:TElemento; begin E := TElemento.create(); E.Asignar(PActual.Elemento); result := E; end;


PActual es un puntero a un nodo de la lista. Esta funcion se complementa con los procedimientos Primero, Ultimo, Siguiente y Anterior para movernos por la lista.

Mi duda es la siguiente: el objeto E es un puntero cuyo espacio (el que ocupa el puntero no a lo que apunta) se libera cuando la funcion termina, es decir, como un tipo simple. Mi pregunta es si a lo que apunta tambien es liberado o soy yo el que tiene que preocuparse de liberar el espacio ocupado por E con el metodo destroy debido a que no es un tipo simple como un entero sino un objeto. Si es asi, significa que esta funcion, a no ser que el que llame a esta funcion se preocupe, cada vez que se llama deja perdido en memoria un espacio equivalente a algo de tipo TElemento o descendiente.


Beno, por ultimo (tranquilidad que no son mas dudas y no sera porque no tenga mas ) agradecer de nuevo las respuestas y la pagina que me han recomendado y por supuesto la paciencia mostrada con las "novelas" que he enviando como mensajes.

Un saludo.

Salud y Delphi
Responder Con Cita