Está en la página 1de 8

Métodos de clase y variables estáticas

Organización de lenguajes y compiladores 2


Aux. Oscar Estuardo de la Mora

Métodos constructores
Tal y como dice su nombre, son los que construyen los objetos, es decir, les dan los valores
iniciales a sus atributos. Todas las clases tienen constructores por default. Por ejemplo:

class Objeto{
int a = 0;
int b = 0;
}
Implícitamente tiene el método constructor que inicializa las variables que están declaradas.

class Objeto {
int a;
int b;
public Objeto(){
a = 0;
b = 0;
}
}

Si creáramos un método constructor parametrizado:


class Objeto{
int a = 0;
int b = 0;
public Objeto(int c){
a = c;
}
}
Implícitamente tendríamos en el código

class Objeto {
int a;
int b;
public Objeto(){
a = 0;
b = 0;
}

public Objeto(int c){


Objeto(); //aunque también equivalente podría ser this();
a = c;
}
}
¿Porque pasa esto?, es porque hay que hay que construir primero las variables de clase y luego
seguir con lo que esta escrito dentro del constructor parametrizado.
Métodos de clase y variables estáticas
Organización de lenguajes y compiladores 2
Aux. Oscar Estuardo de la Mora

Ahora bien ¿que pasa si la clase es hija de una super clase?

public ObjetoHijo extends Objeto{


int x = 0;
int y = 0;
}

Implícitamente tendríamos

public ObjetoHijo extends Objeto{


int x;
int y ;
public ObjetoHijo(){
super();
x = 0;
y = 0;
}
}

Si tuviéramos:

public ObjetoHijo extends Objeto{


int x = 0;
int y = 0;
public ObjetoHijo(int a){
x = a;
}
}
Como podemos ver, el método con
Tendríamos: parámetro, manda a llamar al método por
defecto, y este a su vez manda a llamar al
public ObjetoHijo extends Objeto{
método constructor por defecto padre.
int x;
int y; Pero acá tenemos un problema, no
podemos llamar al constructor por defecto
public ObjetoHijo(){
super(); si en la clase padre existe un constructor
x = 0; parametrizado, hay que llamar a este, en
y = 0; este caso sustituimos por:
}
super(algunInt);
public ObjetoHijo(int a){
this(); //o bien podría ser ObjetoHijo();
x = a;
}
}
Métodos de clase y variables estáticas
Organización de lenguajes y compiladores 2
Aux. Oscar Estuardo de la Mora

Siempre se construirá primero lo del objeto padre, luego las variables de clase y por ultimo lo
que este dentro del método constructor.

Ahora, ¿como funciona a bajo nivel?

Los métodos constructores son básicamente métodos que regresan valores. En este caso, seria
la referencia del objeto construido.

Cuando se encuentra la palabra new, es cuando debemos inicializar nuestro, lo primero que
hacemos es enviar la referencia null al constructor, luego si hubiera más parámetros, también
los preparamos en la pila.

Suponiendo esto:

public static void main(){


Objeto obj = new Objeto();
}

Tenemos en el código tres direcciones:

t1 = ptr + 1; // tamaño del método main para desplazarnos


t2 = t1 + 0; //nos desplazamos a la posición de la referencia
stack[t2] = -1; //inicializo la referencia con null
/* Si hubieran mas parámetros, estos se preparan también */
ptr = ptr + 3; //me desplazo al ámbito del constructor
Objeto_New();

Ahora dentro del método constructor, hacemos tres pasos principales para la creación del
objeto:
Verificar
Direccionar
Reservar memoria

void MyLinkList_New(){
t100 = ptr + 0; //obtenemos la dirección de la referencia
t101 = stack[t100]; //obtenemos el valor de la referencia
if(t101 == -1)goto L100; //verificamos si es null
goto L101;
L100:
stack[t100] = ptrM; //si es null direccionamos
ptrM = ptrM + 2; //y luego reservamos
L101:
//demás código
Métodos de clase y variables estáticas
Organización de lenguajes y compiladores 2
Aux. Oscar Estuardo de la Mora

¿Porque verificamos si la referencia es null? Un objeto puede que tenga clases hijas, si las hay
estas llamaran a los constructores padres. Cuando esto sucede, no se inicializa la referencia
con null, entonces no es necesario direccionar ni reservar, pues se esta modificando el mismo
objeto.
Si fuera null, quiere decir que no hay un objeto creado, y necesita un lugar donde alojarse,
para esto direccionaremos con ayuda de nuestra variable ptrM. Guardaremos en la posición de
la referencia el valor de ptrM (este valor se regresara mas tarde a la instancia donde se esta
creando el objeto), pues este nos indica el siguiente lugar en el Heap que esta libre para
alojarlo.
Luego tenemos la reserva de memoria, en este paso vamos a desplazar la variable ptrM tantas
posiciones como tamaño tenga el objeto, en este caso es de tamaño 2.

Métodos de clase
Estos son los que definen el comportamiento de los objetos, se definen dentro de las clases y
se diferencian de los métodos estáticos porque llevan una variable extra, que es la referencia
del objeto mismo.

class Objeto{
int a;
int b;
public void setA(int z){
this.a = z;
}
}

En su tabla de símbolos tendríamos:

Nombre Tamaño Rol Tipo Dirección


Objeto 2 Clase
a 1 Var de clase Int 0
b 1 Var de clase Int 1
setA 2 Método Void
this 1 Var local Referencia 0
z 1 Var local Int 1
Como vimos anteriormente, los objetos se diferencian unos a otros por su dirección de
memoria, talvez tengan los mismos atributos, pero cuando se debe modificar algún atributo de
un objeto en especifico para saber cual modificar usamos la dirección donde esta localizado en
el Heap.

public static void main(String ar[]){


Objeto obj1 = new Objeto();
Objeto obj2 = new Objeto();
obj1.setA(5);
Métodos de clase y variables estáticas
Organización de lenguajes y compiladores 2
Aux. Oscar Estuardo de la Mora

Para pasar los parámetros se usa el mismo método como con métodos estáticos y/o
constructores, pero primero siempre vamos a preparar la variable que identifica al objeto y
luego pasaremos los demás valores al ámbito del método setA(int).

Si tuviéramos la instrucción:

obj2.setA(10);

Pasaríamos la dirección del objeto que está en la posición cero:

Variables estáticas
Estas variables se llaman de este modo porque tienen una dirección de memoria definida,
estas se inicializan al iniciar el programa y se colocan en el stack de memoria. Si por ejemplo
tuviéramos:

class Clase1{
public static int var1 = 0;
public static int var2 = 0;
}

class Clase2{
Métodos de clase y variables estáticas
Organización de lenguajes y compiladores 2
Aux. Oscar Estuardo de la Mora

public static int varClase2 = 2;


public static int[] vec = null;
}
Tendríamos el stack de memoria de la siguiente manera:

Y efectivamente, el método main() no comenzaría en la posición cero del stack, si no en este


caso, en la posición cuatro. También vemos que existe un arreglo, pero solo tenemos su
referencia en la memoria. Cuando este se inicializa en algún lugar del programa, se reserva
espacio en el heap

vec = new int[5];

Para esta inicialización de variables estáticas tenemos un procedimiento que se ejecuta de


primero en el método main().

void init(){
stack[0] = 0;
stack[1] = 0;
stack[2] = 2;
stack[3] = -1;
ptr = ptr + 4;
}
Métodos de clase y variables estáticas
Organización de lenguajes y compiladores 2
Aux. Oscar Estuardo de la Mora

Debemos tener muy en cuenta que cuando se crean objetos, las variables estáticas que están
declaradas dentro de la clase no van dentro del objeto en el Heap. Es porque no son miembros
de la clase, si quisiéramos acceder a la variable, no necesitamos la dirección de memoria del
objeto, solo saber a que clase pertenece.

Si tuviéramos

class Ejemplo{ Main(){


int a; int a;
int b; Ejemplo ej = new Ejemplo()
static int c; }
int d;
}

El tamaño del objeto es tres, pues la variable ‘c’ es estática y se encuentra al principio del stack
de memoria. Si por ejemplo:

ej.c = 5;
print(ej.c);

nos imprimirá ‘5’. Si tuviéramos otro objeto

Ejemplo otroEjemplo = new Ejemplo();


ej.c = 7;
print(otroEjemplo.c);

Nos desplegara ‘7’, pues se esta modificando la misma variable. El hacer estas instrucciones
son equivalentes a escribir:

print(Ejemplo.c);

Para poder usarlas a bajo nivel, tenemos almacenada la dirección de memoria en la tabla de
símbolos.

Nombre Tamaño Rol Tipo Dirección


c 1 Estática int 0
Cuando encontremos una instrucción donde la use:
Métodos de clase y variables estáticas
Organización de lenguajes y compiladores 2
Aux. Oscar Estuardo de la Mora

a = Ejemplo.c;

Sabemos exactamente donde se encuentra la variable

t1 = stack[0];

t1 va a guardar el valor de la variable estática para luego pasar el valor a la variable ‘a’. Si
tuviéramos otra variable estática y la llamáramos:

b = Ejemplo.x;

Suponiendo que esta continua a la variable ‘c’, tendríamos como código intermedio:

t5 = stack[1];

Debemos recordar siempre desplazar la variable ptr tantos espacios como variables estáticas
tengamos en nuestro programa. Si no lo hacemos, corromperíamos las variables estáticas y
tendríamos un serio error en la implementación del lenguaje.

También podría gustarte