Etiquetado: oop

Variables de clase y de instancia en Smalltalk

Este tema incluye algunas particularidades que me parece en general no se le presta mucha atención y por ello hoy quiero dedicarle un par de líneas.

Analicemos la definición de clase CuentaBancaria:

Object subclass: #CuentaBancaria
	instanceVariableNames: 'numero saldo'
	classVariableNames: 'SiguienteNumero'
	poolDictionaries: ''
	category: 'algo3-ejemplos'

instanceVariableNames, indica las variables de instancia, también conocidas como atributos de instancia. En Smalltalk, estas variables tienen visibilidad protegida aunque en general se las trata como si fueran privadas. En este caso tenemos las variables de instancia numero y saldo. Un detalle interesante es que las variables son protegidas de las instancia, ¿que significa esto? supongamos que tengo dos instancias de la clase CuentaBancaria: cuenta1 y cuenta2, entonces cuenta1 no puede acceder al atributo numero de la cuenta cuenta2, pues si bien cuenta2 es una instancia del mismo tiempo, resulta que otra instancia y aqui la protección es a nivel de instancias.

classVariableNames, como su nombre sugiere son variables de clase, lo cual significa que son accesibles por el objeto clase, pero al mismo tiempo también son accesibles y compartidas por todas las instancias de la clase, o sea, si una instacia modifica el valor de dicha variable, dicho cambio afecta a todas las instancias. En este caso tenemos tenemos el siguienteNumeroDisponible como variable de clase, la cual es incrementada por cada instancia cada es inicializada.

initialize
	saldo := 0.
	numero := siguienteNumero.
	siguienteNumero := siguienteNumero + 1.

Un punto importante para considerar es que esta variable también es accesible por la clase CuentaBancanria.

Por otro lado, si vamos a la definición de la clase CuentaBancaria y vemos la parte de clase, veremos.

CuentaBancaria class
	instanceVariableNames: 'MaximoNumero'

instanceVariablesNames, en este caso representa las variables exclusivas del objeto clase y como tales son accesibles por la clase, pero no por las instancias de  la clase. Un detalle interesante respecto de estas variables es donde inicializarlas. Bien, en general se suele agregar un método de clase que se encarga de inicializarlas, pero ojo este seria un método de clase.

Bien, por último, si volvemos a la definición de la clase CuentaBancaria, veremos que aún nos queda por mencionar los poolDictionaries. Estas variables son variables compartidas por instancias de distintas clases.  Es algo relativamente raro (al menos a mi parecer) y por eso es que no se ocurre como utilizarlas en el ejemplo, pero prometo escribir otro post al respecto.

Para finalizar les ofrezco un gráfico para intentar resumir el ejemplo.

(gracias Mariano por la correción)

 

 

 

Object creation review

When working with OO languages we use constructors to instantiate our objects. Constructors should always return a valid instance ready to use, you don’t need to perform any additional task before using the instance. In some occasions an object need some collaborators to perform its work and in that cases you will need to provide a constructor that takes this collaborators as parameters.

The syntax of constructors may vary depending on the language, in C++like languages (Java, C# and others) constructors take the same name of the class. In cases like Object Pascal (the language behind Delphi) you use the keyword constructor to declare constructors. And finally  we have Smalltalk-like cases, where you constructors are simply class methods, no special name , no keyword, just call them as you like.

One practice I like when defining constructor is to give them some semantic, this is a very common practice for those who work with Smalltalk but it is not so common for those working with C++ like languages. Many times when I work with C# or Java, I find classes that provide several constructors with different parameters, but is not so clear how this constructors work, of course al of them return a valid instance, but do they perform any additional task? is there any particular property in the create instance? Let’s see an example to illustrate it. Let’s define a person class with first name (mandatory) and last name (optional).

In C# we could have something like this:

public class Person
{
public Person (string firstName) {…}
public Person (string firstName, string lastName) {…}
}

And to use it:

Person aPerson = new Person("John");
Person anotherPerson = new Person("John", "Foo");

In Smalltalk this could be:

Object subclass Person
Person class>>withFirstName: aFirstName.
Person class>>withFirstName: aFirstName andLastName: aLastName.

And we use it this way:
aPerson := Person withFirstName: 'John'.
anotherPerson := Person withFirstName: 'John' andLastName: 'Foo'.

As I said, this practice is very common in Smalltalk, but it can be used with C++like languages, in fact it is recommended by Kent Beck in his book Implementation Patters that is focused on Java. Let’s refactor the C# person class to use this pattern.

public class Person
{
public static Person WithFirstName(string firstName) {...}
public static Person WithFirstNameAndLastName(string firstName, string lastName) {...}
}

( I know, Smalltalk’s ability of merging method name and parameters provides a great user experience that is impossible to emulate with C++ like languages. )

titiritero: design decisions

During this week I refactored titiritero and in particular the implementation of the gameloop.  The gameloop is a control structure that runs the simulation (give live to model) and updates the views. There are to ways of implementing it:

The first one, is with an infinite loop with a Thread.sleep inside, something like this:

shouldExecuteGameloop = true;
while(shouldExecuteGameloop ){
   this.runSimulation();
   this.updateView();
   Thread.sleep(simulationInterval);
}

The other alternative is using a Timer object and making the gameloop class to implement TimerTask interface, something like this:

Timer timer = new Timer(gameloop);
timer.start(simulationInterval);
...
gameloop.onTimerTask(){
   this.runSimulation();
   this.updateView();
}

I choose the first alternative because with the second one it could happen that the execution of a single loop of the gameloop takes to much time, so there could be more than one thread working simultaneously on the same object, producing an anomalous behaviors of the application.