close Warning: Can't synchronize with repository "(default)" (/var/svn/tolp does not appear to be a Subversion repository.). Look in the Trac log for more information.

Opened 15 years ago

Closed 15 years ago

#730 closed doubt (duplicate)

Derived Class Instances as Main Class Instances

Reported by: pgea@… Owned by: Víctor de Buen Remiro
Priority: highest Milestone: OOP Implementation
Component: OOP Version:
Severity: blocker Keywords:
Cc:

Description

Al crear clases derivadas como particularizaciones de una clase principal nos encotramos con referencias a objetos de la clase principal que apuntan a instancias de la derivada.

En estos casos, el objeto apuntado (de la clase derivada) pierde los métodos (atributos tipo Code) que le son propios, aunque conserva el resto de atributos de la clase derivada.

Attachments (2)

ticket_7.DerivedClassAsMainClassInstances.tol (908 bytes) - added by pgea@… 15 years ago.
ticket_7.DerivedClassAsMainClassInstances_MOD.tol (2.1 KB) - added by pgea@… 15 years ago.

Download all attachments as: .zip

Change History (7)

Changed 15 years ago by pgea@…

comment:1 Changed 15 years ago by Víctor de Buen Remiro

No veo dónde está el problema.
A mí me parece un comportamiento bastante correcto.
Si declaras una variable de una clase no puedes esperar que tenga métodos que no le pertenecen.
En todo caso quizás debiera dar un warning de que se está asignando algo que no es del tipo esperado.

comment:2 Changed 15 years ago by Víctor de Buen Remiro

Status: newassigned

comment:3 Changed 15 years ago by pgea@…

No estoy tan seguro de que eso no sea un problema.
En mi opinión con el operador "=" se confunden dos cosas como una sola: (i) la asignación de un objeto por referencia y (ii) la construcción misma de una instancia de la clase.
Esta dualidad quizá sea la culpable de extraños comportamientos como el #725.

El asunto es que un objeto de una clase derivada debería poder (como objeto derivado que es) ser referenciado como una instancia de una clase superior pues posee al menos todos los miembros y atributos que ella.

Y de hecho esto puede hacerse (véase "obj3" en el nuevo archivo adjunto) aunque en ocasiones falle (como en "obj5") si no se hace algo rebuscado (como en "obj6").

comment:4 Changed 15 years ago by Víctor de Buen Remiro

Esa dualidad existe desde siempre, no solo en las instancias de clases si no en todos los tipos en los que no se existe la asignación por referencia,
No sé si será culpable de otras cosas pero desde luego no tiene nada que ver con el ticket #725.

Por lo que acabo de ver de hecho no está ocurriendo nada de lo que parece a simple vista.

Lo que está pasando en ambos casos es precisamente lo mismo que en el #725, lo que pasa es que no se ve precisamente porque los miembros del NameBlock de argumento se llaman igual que los miembros de la clase y te da la sensación de que hay un problema de herencia que no existe.

Esto se ve más claramente si renombramos los miembros de la clase anteponiéndoles _.

Class CPrincipal {
  Real _.a;
  Real GetA(Real void){ a }
};

Class CDerivada : CPrincipal {
  Real _.b;
  Real GetB(Real void){ b }
};

CPrincipal ej1 = [[Real _.a = 1]];

CDerivada ej2 = [[Real _.a = 1; Real _.b = 2]];

//////////////////////////////////////////////////////////////////////////////

CDerivada CDerivada.New(NameBlock args) {
  CDerivada new = args
};

CDerivada ej3 = CDerivada.New([[Real a = 1; Real b = 2]]);

// Si asignamos una referencia a un objeto de CPrincipal con una
// instancia de una clase derivada (CDerivada) perdemos
// los métodos (o atributos tipo Code) de la clase derivada.

CPrincipal ej4 = CDerivada.New([[Real a = 1; Real b = 2]]);
// ej4 no posee los métodos propios de CDerivada

Ahora TOL devuelve el mismo error estúpido que en el #725

ERROR: [1] No se pudo crear la instancia ej3 de la clase CDerivada debido a que hay miembros no implementados :
  Real CDerivada::_.b
  Real CPrincipal::_.a

Para comprobar que efectivamente no hay ningún problema con la instanciación soslayando el problema #725 podemos reescribir el código así:

  Class CPrincipal {
    Real _.a;
    Real GetA(Real void){ _.a }
  };
  
  Class CDerivada : CPrincipal {
    Real _.b;
    Real GetB(Real void){ _.b }
  };
  
  CPrincipal ej1 = [[Real _.a = 1]];

  Real ok.1.1 =  ObjectExist("CPrincipal","ej1");
  Real ok.1.2 = !ObjectExist("CDerivada", "ej1");
  
  CDerivada ej2 = [[Real _.a = 1; Real _.b = 2]];

  Real ok.2.1 = ObjectExist("CPrincipal","ej2");
  Real ok.2.2 = ObjectExist("CDerivada", "ej2");
   
  CDerivada CDerivada.New(Real a, Real b) {
    CDerivada new = 
    [[
      Real _.a = a;
      Real _.b = b
    ]]
  };
  
  CDerivada ej3 = { CDerivada.New(Real a = 1; Real b = 2) };
  
  Real ok.3.1 = ObjectExist("CPrincipal","ej3");
  Real ok.3.2 = ObjectExist("CDerivada", "ej3");
  
  // Si asignamos una referencia a un objeto de CPrincipal con una
  // instancia de una clase derivada (CDerivada) perdemos
  // los métodos (o atributos tipo Code) de la clase derivada.
  
  CPrincipal ej4 = { CDerivada.New(Real a = 1; Real b = 2) };
  // ej4 no posee los métodos propios de CDerivada
  
  Real ok.4.1 = ObjectExist("CPrincipal","ej4");
  Real ok.4.2 = ObjectExist("CDerivada","ej4");

Nota: para correr este código será necesario usar la versión "v2.0.1 b.0.10.alpha" o superior que arregla algunos problemas previos.

El método ObjectExist devuelve cierto si existe una instancia de una clase con esos nombres o bien de una clase heredada. Resulta pues que ej4 sí es una instancia de CDerivada y todo ha sido una falsa apariencia debida a efectos colaterales del ticket #725.

comment:5 Changed 15 years ago by Víctor de Buen Remiro

Resolution: duplicate
Status: assignedclosed
Type: defectdoubt

En resumidas cuentas lo que resulta es que este ticket es un duplicado del #725

Note: See TracTickets for help on using tickets.