26.- Tipos complejos o referencia: Variables atributos

 26.- Tipos complejos o referencia: Variables atributos.

Ya hemos visto algunas clases de tipos completos o referencia, como la clase String, la clase Punto y las clases Hora.

Hemos visto como la clase Hora y la clase Punto generan objetos que agrupan 2 datos: x e y para la Clase Punto y h y m para la clase Hora; o bien tres datos: h, m y s para la clase HoraHMS. Los objetos formados con estas clases se crean y manipulan con métodos u operadores que se definen en su propia clase.

Los objetos, o variables referencia, para operar con ellos -cambiar el valor de sus atributos, etc- necesitan estar previamente inicializados, como toda variable, de lo contrario origina un error.

Ejemplo;

                Punto p; //variable referencia sin inicializar.

                p.x =2.43; // error de compilación: variable no iniciada;

otro:

                Punto p1 = null;

                 Punto p2 = p1; // variable referencia con valor null 

                p2.x = 2.34; // Error de ejecución: NullPointerException

El compilador no es capaz de analizar la tercera instrucción, y es al ejecutar donde da el error.

Las variables referencia se INICIALIZAN con el operedor new:

            Punto p = new Punto(0,0); por ejemplo, y entonces si podemos hacer

            p.x = 2.43; el atributo x tomará este valor.


Copia y comparación de objetos.

Para obtener una copia de un objeto en un estado determinado de la ejecución, se debe proceder atributo a atributo. (Al final veremos el método equals para comprobar si las copias son iguales).

Ejemplo:

Punto p1 = new Punto(); p1.x = 3.2; p1.y = -5.1; 

Punto p2 = new Punto(); p2.x = p1.x; p2.y = p1.y; 

Esquema de variables atributo que señalan a objetos en el heap

Cuando se comparan variables de tipo primitivo el operador == da true o false según sean o no iguales los valores de las variables que se comparan.
Ejemplo:
                p1.x==p2.x  se obtiene true;
 • Cuando este operador se aplica a variables de tipo referencia, se comparan las referencias.
               
Si se aplica el operador a dos objetos diferentes, aunque los atributos tengan el mismo valor, el resultado será false.
             p1==p2 se obtiene false;

Objeto desreferenciado: gc:  


p3 es la referencia de valor null, lo cual dice que no está indicando a ningún objeto. Por lo que elobjeto al que anteriormente estaba indicando queda desreferenciado.

      En el caso (1), si hacemos p2==p3 obtenemos true, y si p1 ==p2 obtenemos false

      En el caso (2), si hacemos p2==p3 obtenemos false, y si p1==p2 obtenemos true.

Para obtener una copia de un objeto en un estado determinado de la ejecución, se debe proceder atributo a atributo: método equals() para comprobar si las copias son iguales, siendo dos objetos distintos.

public boolean equals(Object o){
          return o instanceof Punto
         && this.x == ((Punto) o).x 
         && this.y == ((Punto) o).y;
    }
Para las cadenas de caracteres se utiliza el método compareTo(String st);

Modificador de instanciabilidad static:

Los atributos de una clase se replican en cada ejemplar. Pero a veces es necesario tener información común a todos los objetos de una clase.
 • Ejemplo: la dimensión (número de coordenadas) de los objetos de la clase es un dato común de todos los objetos de la clase Punto.
 • Un atributo de clase o estático es una variable mediante la que es posible mantener información común a todos los elementos de la clase. 
• Se declaran con el modificador static.
• El resto de atributos, por diferenciar, se denominan de instancia. 
• Ejemplo: 
    public class Punto { 
        double x; // la abscisa, atributo de instancia 
        double y; // la ordenada, atributo de instancia 
        static int dimensión = 2; // la dimensión, atributo de clase 
public Punto() {}// El constructor
}

El sistema asigna memoria a los atributos static cuando se carga código de la clase para su ejecución, sin necesidad de crear ningún objeto, y se pueden usar citándolas en la forma:
                                        NombreClase.nombreAtributoStatic
 Estos atributos continúan en uso hasta que la clase deja de estar cargada en memoria (normalmente al finalizar el programa que la utiliza).
• Cuando se crean objectos de la clase, los atributos static no se replica en cada instancia. 
• No obstante, Java lo considera también información propia de cada ejemplar, y se puede acceder a él a través de una referencia al objeto, con la notación de punto.

Modificadores de visibilidad public, private:

A menudo la estructura de los objetos de una clase es lo suficientemente compleja como para mantenerla oculta o inaccesible, total o parcialmente. Por ejemplo, cuando un usuario utiliza un objeto Scanner, lo más práctico y seguro es que se desentienda de sus detalles internos.
• Los modificadores private, public sirven para establecer los permisos de acceso a los atributos de un objeto, de acuerdo a las siguientes reglas. Sea C una clase de Java: – Si un atributo de C se ha declarado public, cualquier clase que use objetos de clase C puede acceder a dicho atributo.
• Si un atributo de C se ha declarado private, solamente se puede acceder a dicho atributo en el código escrito dentro de la propia clase C.
 – Por defecto, un atributo es accesible de manera amistosa para las clases que se encuentran en la misma carpeta y en otros casos que se estudian posteriormente.

Decidir qué atributos se hacen públicos y cuáles privados dependerá del uso que pretenda el programador para la clase y sus objetos.
 • Ejemplo:
En la clase Math se declaran dos atributos public: 
                     public static final double PI = 3.141592653589793;
                     public static final double E = 2.718281828459045;
En cambio en la clase String los atributos que guardan los caracteres son privados.
 • Los atributos públicos aparecen en la interfaz que se genera de la clase. 

Organización de clases: paquetes Java:

Las clases predefinidas de Java vienen clasificadas en paquetes (package): grupos de clases que pueden ser importadas conjuntamente para ser usadas en un programa.

El paquete java.lang se importa por defecto. Forman parte de este paquete las clases System, String y Math. 
• El resto de paquetes deben importarse explícitamente. 
• Ejemplo.
La clase Scanner se encuentra en el paquete java.util. Para poder usarla en una clase hay que incluir al principio la cláusula import java.util.*; 

Las clases nuevas también se pueden agrupar en un paquete:
 – Se escriben en una misma carpeta que tendrá el nombre del paquete, 
– Se declara el nombre del paquete al principio del fichero que contiene a cada una de las clases de dicho paquete.
 – En las clases de un mismo paquete el acceso es amistoso (public por defecto). 
– Por defecto, Java considera que cualquier clase se encuentra en un mismo paquete anónimo. 
– La instalación del paquete (más allá de la carpeta en la que se encuentra) consiste en incluir su ubicación en la variable de entorno CLASSPATH del sistema. Java revisa esta ubicaciones para buscar los paquetes importados.
 – BlueJ da facilidades para automatizar la formación de paquetes y su instalación.

Para pequeños programas o aplicaciones puede ser suficiente escribir las clases relacionadas en un mismo proyecto (paquete anónimo).

Comentarios

Entradas populares de este blog

13 Tipo primitivo Char.

11.- Variable constante

27.- Tipos complejos o referencia: Métodos