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 16 years ago

Closed 16 years ago

#713 closed doubt (fixed)

Llamar a un método de una clase desde el constructor

Reported by: Javier Portugal Owned by: Víctor de Buen Remiro
Priority: highest Milestone: OOP Implementation
Component: OOP Version: 2.0.1
Severity: major Keywords:
Cc:

Description

Hola,

Simulando clases con NameBlocks puedo hacer lo siguiente:
Tengo una clase que define que para cada objeto hay un conjunto con elementos y para llenar estos conjuntos lo quiero hacer con un texto que codifica estos elementos (la cantidad en el ejemplo, podría tener más datos). Es decir, puedo llamar al método AddItemsFromCodif desde el 'constructor'

NameBlock Objeto.New(NameBlock args) 
{
  [[ 
    Text _.codif = args::_.codif;
    Set _.items = Copy(Empty);
    Real AddItemsFromCodif(Real void) {
      Text val_ = Sub(_.codif,2,TextLength(_.codif));
      Real val = Eval("Real "+val_);
      Set For(1, val, Set (Real i) {
        Set Append(_.items, SetOfReal(i))
      });
      val
    };
    Real _numItems = AddItemsFromCodif(0)
  ]]
};

NameBlock miObj = Objeto.New(
[[
  Text _.codif = "P2"
]]);

Sin embargo con clases no puedo hacer lo siguiente:

Class Objeto
{
   Text _.codif;
   Set _.items = Copy(Empty);
   Real AddItemsFromCodif(Real void) {
     Text val_ = Sub(_.codif,2,TextLength(_.codif));
     Real val = Eval("Real "+val_);
     Set For(1, val, Set (Real i) {
        Set Append(_.items, SetOfReal(i))
     });
     val
   };
   Real _numItems = AddItemsFromCodif(0)
};

Objeto miObj =
[[
  Text _.codif = "P2"
]];

Da el error de que todavía no existe el atributo _.codif
_.codif no es un objeto valido para el tipo Text.

Estando obligado a hacer:

Class Objeto
{
   Text _.codif;
   Set _.items = Copy(Empty);
   Real AddItemsFromCodif(Real void) {
     Text val_ = Sub(_.codif,2,TextLength(_.codif));
     Real val = Eval("Real "+val_);
     Set For(1, val, Set (Real i) {
        Set Append(_.items, SetOfReal(i))
     });
     val
   }
};

Objeto miObj =
[[
  Text _.codif = "P2"
]];
Real miObj::AddItemsFromCodif(0);

Creo que sería deseable que se pueda hacer lo anterior. ¿Es posible? ¿Se recomienda la programación del último ejemplo?

Change History (1)

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

Resolution: fixed
Status: newclosed
Type: enhancementdoubt

La solución que das no me parece mal aunque pierdes lo que te devuelve la llamada a AddItemsFromCodif, que en tu diseño original parece ser que querías que fuera un miembro oculto. Además crea confusión tener que llamar desde fuera del objeto al método que lo construye.

Es evidentemente imposible hacer lo que quieres hacer como lo quieres hacer. Simplemente no está definido _.codif así que no lo puedes usar aún. ¿Cómo va a adivinar un mero reconocedor sintáctico que tiene que crear primero el miembro _.codif y luego _numItems ? No existe ninguna forma de saberlo a priori sin entender la semántica, lo cual no es exigible a un lenguaje de programación.

Si un miembro no está definido no puedes pretender definir previamente otros que dependen de él. Es decir, tienes que definir, no sólo los miembros sino en el orden adecuado. En C++ y otros lenguajes no hay problema porque se declaran siempre en la clase y se definen obligatoriamente fuera de ella, pero en un lenguaje interpretado nos podemos permitir el lujo de hacerlo todo dentro de la clase. Lo lógico en este caso es dejar tanto _numItems como _.codif sin definir en la clase, puesto que ambas son variables en las instancias

Class Objeto
{
   Text _.codif;
   Real _numItems;
   Set _.items = Copy(Empty);
   Real AddItemsFromCodif(Real void) {
     Text val_ = Sub(_.codif,2,TextLength(_.codif));
     Real val = Eval("Real "+val_);
     Set For(1, val, Set (Real i) {
        Set Append(_.items, SetOfReal(i))
     });
     val
   }
};

Y luego en la instanciación se definen las dos en el orden adecuado de dependencia:

Objeto miObj =
[[
  Text _.codif = "P2";
  Real _numItems = AddItemsFromCodif(0)
]];

Otra posibilidad igualmente válida sería que le pasaras el texto codificado como argumento de AddItemsFromCodif, aunque entonces el miembro _.codif debería estar inicializado. Por coherencia también le doy valor por defecto a _numItems

Class Objeto
{
   Text _.codif = "";
   Real _numItems = 0;
   Set _.items = Copy(Empty);
   Real AddItemsFromCodif(Text codif) {
     Text _.codif := codif;
     Text val_ = Sub(_.codif,2,TextLength(_.codif));
     Real val = Eval("Real "+val_);
     Set For(1, val, Set (Real i) {
        Set Append(_.items, SetOfReal(i))
     });
     val
   }
};

Objeto miObj =
[[
  Real _numItems = AddItemsFromCodif("P2")
]];
Note: See TracTickets for help on using tickets.