Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Se puede hacer esto en POO? (https://www.clubdelphi.com/foros/showthread.php?t=25401)

adlfv 21-09-2005 16:39:53

Se puede hacer esto en POO?
 
1 Archivos Adjunto(s)
Hola a todos.

Tengo un problema de POO y no sé si es posible hacer lo que quiero hacer, pero me imagino que sí, el problema es que no sé cómo... A ver si alguien me puede echar una mano.

Tengo una clase TBaseHabitacion, de la cual heredan otras clases qeu representan habitaciones en un estado concreto; por ahora la jerarquía es más o menos así...

TBaseHabitacion
- THabOcupada (abstracta)
- THabOcupadaCliente (abstracta)
- THabRenovada
- THabWarning
- THabVencida
- THabOcupadaPersonal (abstracta)
- THabLimpieza
- THabMantenimiento
- THabNoOcupada (abstracta)
- THabReserva
- THabDisponible

La idea es en el objeto Habitaciones (que es la lista de las habitaciones) poder hacer algo como esto (similar a AsInteger, AsBoolean de TField):

Código Delphi [-]
if Habitaciones['01'].IsOcupadaCliente then
   ShowMessage('El nombre del cliente es: ' + Habitaciones['01'].AsOcupadaCliente.Nombre);
A la hora de implementar el método "AsOcupadaCliente: THabOcupadaCliente", me dí cuenta que no se podía incluir en TBaseHabitación porque el compilador aún no sabe nada de esa clase THabOcupadaCliente debido a que se implementa después, y hereda de TBaseHabitacion... Existe alguna forma de implementar estos métodos en TBaseHabitación? Esto lo resolví haciendo como un "wrapper" de TBaseHabitacion al final del todo...

Hasta aquí todo claro... Ahora viene "el dilema" :(

Después me di cuenta que al analizar cada habitación para saber su estado, tendría que estar destruyendo y volviendo a crear y buscar los tipos de habitaciones cada vez (lo cual es muy ineficiente) pues la idea es crear la habitación una sola vez, al igual que obtener el tipo de la habitación (pues se supone que no cambiarán)... Entonces pensé en separar lo que es la información "basica" de una habitación (Id, estado...) de la información "especifica" de esa habitación, incluyendola como una clase, de forma que al analizar cada habitación sólo tenga que crear/destruir la información específica de la habitación.

Pero esto no parece muy compatible con el planteamiento inicial de la jerarquía de las habitaciones, porque la información específica la incluyo como una propiedad de TBaseHabitación, pero no puedo "redefinir" dicha propiedad especializando su tipo en clases descendientes, es decir, Info en TBaseHabitación es de tipo TBaseInfo, pero Info en THabOcupadaCliente debería ser de tipo TInfoOcupadaCliente...

Al ver esto... lo primero que se me vino a la cabeza fue... Estoy "reduciendo el problema al mismo problema :confused:"... Y dije... bueno, hago lo mismo para la info... es decir...

Código Delphi [-]
if Habitaciones['01'].IsOcupadaCliente then
   ShowMessage('El nombre del cliente es: ' + Habitaciones['01'].Info.AsOcupadaCliente.Nombre);
Pero al ver la jerarquía de la información en función del estado, me pasa lo mismo, tendría que hacer otro wrapper.

Código Delphi [-]
 Hab.Info := TInfoOcupadaCliente.Create;
 ShowMessage('Hab=' + IntToStr(H));
 with Hab.Info.AsOcupadaCliente do
 begin
   IdAlquiler     := FieldByName('IdAlquiler').AsInteger;
   IdCliente      := FieldByName('IdCliente').AsString;
   IdVehiculo     := FieldByName('IdVehiculo').AsInteger;
   IdPaquete      := FieldByName('IdPaquete').AsString;
   Entrada        := FieldByName('Entrada').AsDateTime;
   SalidaEstimada := FieldByName('ProximaMax').AsDateTime;
 {...}
El problema es que, no veo forma de que el siguiente código funcione correctamente, porque si Info es de tipo TBaseInfo, me da error al intentar acceder a AsOcupadaCliente, pues está implementado en el wrapper, pero si es de tipo TWrapperInfo, entonces me da error al hacer el create...

Entonces qué hago?

Qué estoy haciendo mal?

Se puede simplificar toda esa estructura y esa jerarquía?

Le agradezco enormemente a cualquiera que se haya tomado la molestia de leer el mensaje, porque para entender este toston, no es muy facil que digamos.

Muchas gracias a todos, agradezco sus comentarios.

Un cordial saludo :p

PD: Incluyo los interfaces de las clases citadas, por si alguien tiene dudas o quiere ver el código.

delphi.com.ar 21-09-2005 17:16:06

Cita:

Empezado por adlfv
A la hora de implementar el método "AsOcupadaCliente: THabOcupadaCliente", me dí cuenta que no se podía incluir en TBaseHabitación porque el compilador aún no sabe nada de esa clase THabOcupadaCliente debido a que se implementa después, y hereda de TBaseHabitacion... Existe alguna forma de implementar estos métodos en TBaseHabitación?

Puedes valerte de Forward declarations, este ejemplo lo extraje de la ayuda de Delphi:
Código Delphi [-]
type
  TFigure = class;  // forward declaration
  TDrawing = class
    Figure: TFigure;
     ...
  end;
  TFigure = class  // defining declaration
    Drawing: TDrawing;
     ...
  end;

¿Es simplemente eso o no te entedí?

Por otro lado, te parece clasificar tanto las habitaciones en lugar de que cuando una este ocupada o no este sea un mero dato de una misma clase?

mamcx 21-09-2005 17:48:25

Sinceramente, me parece un abuso del uso de la herencia, Es una jerquia muy densa, donde cada subclase aporta poco. Estas armando una jerarquia donde deberia ir un manejo de estados y poliformismo.

Es cierto que es mas simple manejar clases sin estado (por ejemplo, en vez de tener una clase que lea y escriba archivos, tener un LectorArchivo y un EscribeArchivo).

Pienso que deberias dibujar (asi sea a lapiz) las clases y sus estados. Reduce la jerarquia y maneja una propiedad con el estado. En lo poco que se ve, me parece que solo existen 2 clases practicas aqui:


THabOcupada
THabNoOcupada

y el resto por poliformismo. Luego un administrador de Habitaciones (que se encarge de cambiar de una ocupada a una desocupada, etc...)

Para evitar borrar y crear los objetos sin necesidad, puedes sobreescribir el metodo Assign (debes derivar de TPersistent)

En fin, echale cabeza al diseño. Te daras cuenta cuando quedo bien hecho, porque veras que no hay que "hackealo" pa que funcione :)

Crandel 22-09-2005 06:57:19

Como dijo mamcx, creo que es un abuso de jerarquía, pero veo las clases:
* THabitacion.
* TCliente.

La clase es THabitacion y el resto son estados de él

IsOcupadaCliente es una propiedad que verifica el Estado y devuelve verdadero o falso.

TCliente es otra clase que tiene los datos de cada cliente.

Luego tendrias que tener una lista de clientes.

y cuando se ocupa una habitación lo que haces es asiganarle el cliente a la habitación, de manera de hacer, por ejemplo:
Habitacion.Cliente.Nombre

De esta forma tambien te va a resultar mucho más facil en un futuro si queres almacenar los datos en una base de datos, en archivo de texto o lo que sea.

maeyanes 22-09-2005 17:24:20

Ampliando un poco lo dicho por Crandel:

La clase THabitación puede tener una propiedad Estado, tal que:

Código Delphi [-]
TEstadoHabitacion = (ehDisponible, ehReservada, ehOcupadaCliente,
  ehOcupadaPersonal, ehRenovada, ehWarning, ehVencida, ehLimpieza,
  ehMantenimiento);

THabitacion = class
private
  FEstado: TEstadoHabitacion;

  function GetIsOcupadaCliente: Boolean;
public
  property Estado: TEstadoHabitacion read FEstado write FEstado;
  property IsOcupadaCliente: Boolean read GetIsOcupadaCliente;
end;

implementation

procedure THabitacion.IsOcupadaCliente: Boolean;
begin
  Result := FEstado = ehOcupadaCliente
end;

Saludos...

adlfv 22-09-2005 17:41:54

Muchas gracias a todos por contestar...

Lo que pasa es que estoy "reinventando la rueda"... Llevo un tiempo ya con este programa, y lo había hecho todo "a lo bestia" prescindiendo de la POO, empleando basicamente un vector y un tipo enumerado... Ahora estoy rehaciendo todas las tripas del programa para hacerlo lo mejor posible para posibles expansiones, personalizaciones y mejoras en el futuro...

Y bueno, con la mentalidad "hibrida" de antes y ahora, a veces lo obvio no se vé tan claro jeje :o.

Es horriiiiiiiible la labor de re-ingeniería... Lo ideal hubiera haberlo hecho bien desde un principio, prácticamente lo que he hecho ha sido tiempo perdido... Lo único que sí he podido aprovechar es el diseño de la base de datos... El resto, mucho lo he tenido que retocar, o rehacer... Espero que el resultado final sea ampliamente "escalable" y flexible...

Muchas gracias de nuevo a todos.

Un cordial saludo...

delphi.com.ar 23-09-2005 13:36:20

Cita:

Empezado por adlfv
Es horriiiiiiiible la labor de re-ingeniería...

No creo eso!.. creo que a la mayoría de los programadores nos encantaría rediseñar lo que está funcionando...

adlfv 23-09-2005 14:17:43

Sí claro, a mi me gusta...

Me refería a que resulta doloroso ver que "lo que funcionaba" ya no funciona al estar en proceso de reconstrucción... Eso sí es horrible... Pero va dando gusto cuando empieza a funcionar de nuevo :p.

rastafarey 26-09-2005 16:28:55

Resp
 
Si necesitas algun metodo que no existe en un aclase y es eredada simplemete has un casting pero si solo quieres que lo smetodos no sean implemtados por la supercalse(clase base) y se implmemnten el los heredados usa metodos abstractos el cla clase base o virtuale si levan algun codigo en comun y le haces un overrride en la caklse que lo heredan.


La franja horaria es GMT +2. Ahora son las 17:42:18.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi