Club Delphi  
    Paypal   FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Coloboración Paypal con ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 07-04-2011
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por rgstuamigo Ver Mensaje
cada objeto al momento de destruirse ya, él por si mismo debería ponerse en nulo. ¿me entiendes?
Te entiendo, pero no estoy de acuerdo por dos razones:

1. Quien se pone nulo no es el objeto sino una referencia al objeto. Diferencia sutil pero importante. Puedes tener múltiples referencias a un mismo objeto, así que, ¿cuál de ellas es la que se pondría en nulo al momento de destruir el objeto? Eso es algo que puede decidir quien creó al objeto, mas no el objeto en sí.

2. Como no sea una suerte de patrón singleton, por lo general puedes tener varias instancias de una misma clase. Aún en el caso de formularios que en un determinado contexto quieres abrir una sola vez. Entonces, ¿a cuál de estas instancias se debe referir el destructor de la clase?

Por otra parte,

Cita:
Empezado por rgstuamigo
yo diría que es otra forma de hacer lo mismo que hice en el post 26,claro de una forma un poco más elegante , si te dás cuenta igualmente estás haciendo uso de un variable privada, fuera de la clase
no es que sea más elegante, sino que es fundamentalmente distinta. Mi variable privada se anula fuera de la clase y lo hace quien creo la instancia.


Yo diría, en una especie de resumen, que las referencias a un objeto son entidades ajenas a la clase del objeto (y al objeto mismo).

// Saludos
Responder Con Cita
  #2  
Antiguo 07-04-2011
Avatar de rgstuamigo
rgstuamigo rgstuamigo is offline
Miembro
 
Registrado: jul 2008
Ubicación: Santa Cruz de la Sierra-Bolivia
Posts: 1.646
Poder: 20
rgstuamigo Va por buen camino
Arrow

Cita:
Empezado por roman Ver Mensaje
Te entiendo, pero no estoy de acuerdo por dos razones:

1. Quien se pone nulo no es el objeto sino una referencia al objeto.
...
2. Como no sea una suerte de patrón singleton, por lo general puedes tener varias instancias de una misma clase.
Bueno eso ya sabemos amigo roman y eso no está en discucion... no mezclemos las cosas

Cita:
Empezado por roman Ver Mensaje
Por otra parte,

...
no es que sea más elegante, sino que es fundamentalmente distinta. Mi variable privada se anula fuera de la clase y lo hace quien creo la instancia.


Yo diría, en una especie de resumen, que las referencias a un objeto son entidades ajenas a la clase del objeto (y al objeto mismo).
Haber... tú mismo criticaste el hecho de que se usara la variable global que genera Delphi a crear un formualrio, pero si analizamos tu solucion pues basicamente hace lo mismo, claro ahora ya no es una variable Global sino privada, pero de igual manera se la está usando practicamente para hacer lo mismo, pero mejor me explico con un ejemplo siguiendo tu propia solución:
Si por ejemplo instanciaramos un objeto de la clase "TChildForm" de la siguiente forma:
Código Delphi [-]
if otroForm = nil then// OtroForm es otra instacia diferente de ChildForm
 begin
   otroForm := TChildForm.Create(Self);
   otroForm.FreeNotification(Self);
 end;
otroForm.Show;
Para que tu solucion funcione tambien con "OtroForm" deberiamos modifcar el método Notification de la siguiente forma:
Código Delphi [-]
procedure TParentForm.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;

  if (AComponent = ChildForm) and (Operation := opRemove) then
    ChildForm := nil;
//lineas aumentadas
 if (AComponent = OtroForm) and (Operation := opRemove) then
    OtroForm := nil;
{ohora te podas imaginar que ocurre si seguimos creando mas instancias con diferentes referencias..  }
end;
Eso quiere decir que por cada nueva referencia tengo que aumentar código al método Notification..y eso no es ideal amigo seamos realista.
En otras palabras estamos restringidos a crear un objeto solo atraves de la variable "ChildForm", si quisieramos que la cosa siga funcionando y evitar agregar más código; y..pues es practicamente lo mismo que hacer uso de la varible global que gerera delphi, asi que por ese lado no hay diferencia.
Bueno... para no hacerla muy larga la cuestion...pues voy a volver a hacer la pregunta:
¿Es posible implementar una solucion que esté dentro de la misma clase sin utilizar alguna variable en sí? es decir al momento de Destruir(Action:=caFree el Objeto hacer que la referencia del objeto sea nula(nil)?? ¿será posible eso?
__________________
"Pedid, y se os dará; buscad, y hallaréis; llamad, y se os abrirá." Mt.7:7
Responder Con Cita
  #3  
Antiguo 07-04-2011
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Dices esto:

Cita:
Empezado por rgstuamigo Ver Mensaje
Bueno eso ya sabemos amigo roman y eso no
está en discucion... no mezclemos las cosas
y sin embargo preguntas esto

Cita:
Empezado por rgstuamigo Ver Mensaje
¿Es posible implementar una solucion que esté dentro de la misma clase sin utilizar alguna variable en sí? es decir al momento de Destruir(Action:=caFree el Objeto hacer que la referencia del objeto sea nula(nil)?? ¿será posible eso?
¿Cuál objeto? ¿Cuál de todos los objetos que pueden crearse de una clase quieres que se ponga en nulo? Pero, sobre todo, ¿cuál de todas las referencias al objeto quieres que se ponga nula? Pues, aunque lo desestimas, es una diferencia importante que, por tu argumentación, parece que no tienes clara.

// Saludos
Responder Con Cita
  #4  
Antiguo 07-04-2011
Avatar de rgstuamigo
rgstuamigo rgstuamigo is offline
Miembro
 
Registrado: jul 2008
Ubicación: Santa Cruz de la Sierra-Bolivia
Posts: 1.646
Poder: 20
rgstuamigo Va por buen camino
Question

Cita:
Empezado por roman Ver Mensaje
..
¿Cuál objeto? ¿Cuál de todos los objetos que pueden crearse de una clase quieres que se ponga en nulo? Pero, sobre todo, ¿cuál de todas las referencias al objeto quieres que se ponga nula? Pues, aunque lo desestimas, es una diferencia importante que, por tu argumentación, parece que no tienes clara.

// Saludos
Bueno... a lo que me refiero roman es a que si es posible que cualquier referencia, al destruirse el objeto al que apunta, se pueda poner en nula, pero lo que se quiere es que la solucion para eso esté dentro de la misma clase no fuera de ella... ¿Es posible hacerlo o no?
Por favor responde la pregunta...sin vueltas...
__________________
"Pedid, y se os dará; buscad, y hallaréis; llamad, y se os abrirá." Mt.7:7
Responder Con Cita
  #5  
Antiguo 07-04-2011
[maeyanes] maeyanes is offline
Capo de los Capos
 
Registrado: may 2003
Ubicación: Campeche, México
Posts: 2.732
Poder: 26
maeyanes Va por buen camino
Hola...

Cita:
Empezado por rgstuamigo Ver Mensaje
Bueno... a lo que me refiero roman es a que si es posible que cualquier referencia, al destruirse el objeto al que apunta, se pueda poner en nula, pero lo que se quiere es que la solucion para eso esté dentro de la misma clase no fuera de ella... ¿Es posible hacerlo o no?
Por favor responde la pregunta...sin vueltas...
Pues el ya mencionado FreeAndNil ya realiza lo que pides.


Saludos...
__________________
Lee la Guía de Estilo antes que cualquier cosa. - Twitter
Responder Con Cita
  #6  
Antiguo 07-04-2011
Avatar de rgstuamigo
rgstuamigo rgstuamigo is offline
Miembro
 
Registrado: jul 2008
Ubicación: Santa Cruz de la Sierra-Bolivia
Posts: 1.646
Poder: 20
rgstuamigo Va por buen camino
Arrow

Cita:
Empezado por maeyanes Ver Mensaje
Hola...



Pues el ya mencionado FreeAndNil ya realiza lo que pides.

No maeyanes.. eso es fuera de la clase.. y aparte estamos hablando de destruir con el método Release y no con Free...
__________________
"Pedid, y se os dará; buscad, y hallaréis; llamad, y se os abrirá." Mt.7:7
Responder Con Cita
  #7  
Antiguo 07-04-2011
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por rgstuamigo Ver Mensaje
Por favor responde la pregunta...sin vueltas...
No sé.

// Saludos
Responder Con Cita
  #8  
Antiguo 07-04-2011
Avatar de rgstuamigo
rgstuamigo rgstuamigo is offline
Miembro
 
Registrado: jul 2008
Ubicación: Santa Cruz de la Sierra-Bolivia
Posts: 1.646
Poder: 20
rgstuamigo Va por buen camino
Thumbs up

Pues aunque no lo creas, yo tampoco conosco una solucion efectiva... . la única solucion que quise implementar fue la siguiente:
Código Delphi [-]
procedure TChildForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
Self:=nil;//lamentablemente en mi delphi 7 ésta instrucion nunca se ejecuta no acabo de entender por qué
end;
Pero como puedes ver en mi Delphi 7 nunca se ejecuta la segunda instruccion, lo cual me parece misterioso, ya que tal solucion es válida para otros lenguajes de programacíon como por ejemplo C++, Java.
Rogaría a algun miembro que tenga las últimas versiones de Delphi a que pruebe y nos comente...
Saludos...
__________________
"Pedid, y se os dará; buscad, y hallaréis; llamad, y se os abrirá." Mt.7:7
Responder Con Cita
  #9  
Antiguo 07-04-2011
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.610
Poder: 32
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Hola Roberto.

Me resulta algo humorística la forma en que afrontas a Román en los últimos mensajes, pero tal humorismo surge principalmente por la combinación de dos cosas: la idea (interesante, por cierto) de que una clase sea capaz de conocer todas las referencias a sus instancias, y por otro lado, que no pareces tener muy claro lo que Self significa en Delphi (y claro, también por tantas caritas ).

No sé por qué en otros lenguajes se permite la sentencia que señalas (y me gustaría saber), mas en Delphi Self es un parámetro, no declarado, de todos los métodos, y es básicamente la instancia para la cual se está ejecutando el método (intuyo que esto de alguna forma ya lo sabías). Ignoraba que Delphi "permitiese" referencias de escritura en el parámetro Self (para mí siempre ha sido una referencia de solo lectura), pero no me extraña en absoluto que el compilador la deseche sin generar instrucción máquina alguna para esa sentencia (lo puedes verificar con la ventana CPU).

Y es que Self no podría ser variable objeto alguna, todas las variables objeto son punteros (apuntadores) hacia la región de memoria donde se encuentra un "Self", es decir, donde se encuentra una instancia de objeto. Entonces, si se pudiera asignar Nil a Self, lo que se estaría poniendo en blanco sería esa instancia, no las variables que apuntan a ella.

Ahora, aunque hay argumentos muy sólidos para proponer que las clases no conozcan sus instancias y las referencias a éstas, hay casos donde sí pudiera ser conveniente una capacidad similar. Yo tengo una clase derivada de TClientDataSet, con varios métodos que necesitan conocer cuáles otras instancias de la clase comparten la misma base (propiedad DSBase).

Lo solucioné con una lista privada (declarada como variable global en la sección Implementation), y usando el constructor para agregar cada nueva instancia a la lista y el destructor para quitar tal instancia de la lista.
Código Delphi [-]
  Type
    TDataSetList = Class (TList)
      Function GetItem (Const Index :Integer) :TMagiaClientDataSet;
      Property Items [Const Index :Integer] :TMagiaClientDataSet
        Read GetItem; Default;
    End;

  Var
    DataSets :TDataSetList;

...

  Constructor TMagiaClientDataSet.Create (AOwner :TComponent);
  Begin
    Inherited Create (AOwner);
    AutoApplyDetails := True;
    AutoCancelDetails := True;
    AutoEdit := True;
    ChangeCheckFieldTypes := [ftString, ftSmallint, ftInteger, ftWord,
      ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime,
      ftAutoInc, ftFixedChar, ftWideString, ftLargeint, ftVariant, ftGuid,
      ftTimeStamp, ftFMTBcd];

    If DataSets = Nil Then
      DataSets := TDataSetList.Create;

    DataSets.Add (Self);
  End;

  Destructor TMagiaClientDataSet.Destroy;
  Begin
    DataSets.Remove (Self);
    FreeAndNil (FDetailList);
    BlockReadSizeStack.Free;
    FSavePoints.Free;
    Inherited Destroy;
  End;

...

  Function TMagiaClientDataSet.IsBase (Const DataSetIndex :Integer)
    :Boolean;
  Begin
    Result := DataSets [DataSetIndex].DSBase = DSBase;
  End;

...

  Function TMagiaClientDataSet.FindSavePoints
    :TMagiaClientDataSetSavePoints;
  Var
    I :Integer;
  Begin
    If FSavePoints = Nil Then
      For I := 0 To DataSets.Count - 1 Do
        If IsBase (I) And (DataSets [i].FSavePoints <> Nil) Then
        Begin
          Result := DataSets [i].FSavePoints;
          Exit;
        End;

    Result := FSavePoints
  End;

...

Finalization
  DataSets.Free;

Independientemente de lo que dicten los cánones de la POO, esta implementación me resulta eficiente para mis propósitos. Sin embargo, esto es sólo mantener una lista de las instancias creadas de una clase, mas no de las variables que hacen referencia a dichas instancias.

Si quisiéramos que se mantuviera también una lista de tales referencias entraríamos a un terreno un tanto peliagudo, ya que implicaría necesarias modificaciones al compilador Delphi mismo, a fin de que siempre que se ejecute una asignación de instancia de objeto a una variable, tal variable se "marque" para ser limpiada cuando el objeto se destruya:
Código Delphi [-]
Obj1 := TClase.Create...;  // Se "ficha" a Obj1
Obj2 := Obj1;   // Se "ficha" a Obj2
Obj3 := DataSource1.DataSet;  // Se "ficha" a Obj3
...
Obj2.Free;  // Se ponen en blanco (Nil) las variables Obj1 y Obj2
DataSource1.DataSet.Free  // Se pone en blanco (Nil) la variable Obj3

O bien, que no fuese obligatorio "fichar" a la variable, e implementar nosotros mismos un mecanismo "casero" general, con una lista global y una par de funciones AssignObj y FreeObj:
Código Delphi [-]
AssignObj (Obj1, TClase.Create...);  // Se "ficha" a Obj1
AssignObj (Obj2, Obj1);   // Se "ficha" a Obj2
AssignObj (Obj3, DataSource1.DataSet);  // Se "ficha" a Obj3
...
FreeObj (Obj2);  // Se ponen en blanco (Nil) las variables Obj1 y Obj2
Lo pongo como ejemplo, pero lo desaconsejo, porque ¿cómo resolver un caso como este?:
Código Delphi [-]
DataSource1.DataSet.Free;  // Esto NO pondrá en Nil a la variable Obj3

Ahora, sí se realizaran las modificaciones al compilador para que toda asignación de objeto guardara en una lista interna la variable a la cual se asigna, de tal forma que al destruirse tal objeto todas las variables que apunten a él se pongan en Nil, habría que considerar lo mismo para los parámetros de las funciones:
Código Delphi [-]
Procedure X (DataSet :TDataSet;...);
Begin
  If Not DataSet.Active Then
    Exit;
  
  DataSet.Append;
  ...
  ... // Aquí llamada a una rutina que llama a otra que destruye a DataSet
  ... // Aquí el parámetro DataSet deberá volverse Nil
End;
Agrego: Y que las variables y parámetros se eliminaran de dicha lista interna al quedar fuera de ámbito.

Como podrás ver, son varias y muy importantes las implicaciones que tendría modificar el compilador para que las variables objeto nunca apunten a los vestigios de una instancia (es decir, para que se vuelvan Nil cuando la instancia sea destruida).

Pero sí es posible crear una clase particular con este comportamiento, donde esa clase mantenga una lista de punteros, que no serían punteros a las instancias, sino punteros a las variables objeto. De tal forma que el destructor de la clase se encargue de recorrer esa lista y poner a cada variable objeto en Nil. Sin embargo, esto requeriría de un "contrato" entre el creador de la clase y el programador que la usara. Algún párrafo de documentación donde se le diga algo como: Si usted quiere que una variable objeto de esta clase sea limpiada automáticamente, debe usar el método AssignToVar:
Código Delphi [-]
TClase.Create (...).AssignToVar (Obj1);  // En lugar de "Obj1 := TClase.Create (...)"
Obj1.AssignToVar (Obj2);  // En lugar de Obj2 := Obj1;

Yo solía hacerme este tipo de planteamientos casi filosóficos, al grado de crear rutinas de código extravagantes. Con el tiempo uno se va dando cuenta de los pros y contras de cada técnica, hasta que se tiene algún grado de experiencia como para proponer cambios en un lenguaje o en un compilador. Al menos a mí, me gustaría que las clases tuviesen mecanismos nativos para conocer todas sus instancias; pero si esto sonara como un disparate, quizá se deba a que me falta experiencia para darme cuenta de que eso sería un despropósito, o quizá no.

Pero tratándose de variables objetos, creo que lo mejor es seguir dejando la responsabilidad en manos del programador que declara y hace uso de esas variables; algo que me parece Román ya te había comentado.

Un abrazo objetivo.

Al González.

Última edición por Al González fecha: 07-04-2011 a las 23:30:27.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Forms: FreeAndNil ó Release y la validación Assigned? jbautista Varios 13 09-02-2010 17:33:03
Assigned y Free gluglu Varios 4 14-05-2007 21:03:37
Problemas FreeAndNil OscarG OOP 4 09-11-2005 12:48:46
Free Pascal 2.0 marcoszorrilla Noticias 6 19-05-2005 12:04:51
Componente free... Mauro® Varios 10 12-06-2004 13:15:24


La franja horaria es GMT +2. Ahora son las 03:34:55.


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