lunes, 20 de febrero de 2012

2.2 Instanciación de una clase

Para descargar el documento de este tema, haz clic aquí

La instanciación de las clases: Los objetos
Referencias a Objeto e Instancias
Los tipos simples de Java describían el tamaño y los valores de las variables. Cada vez que se crea una clase se añade otro tipo de dato que se puede utilizar igual que uno de los tipos simples. Por ello al declarar una nueva variable, se puede utilizar un nombre de clase como tipo. A estas variables se las conoce como referencias a objeto.
Todas las referencias a objeto son compatibles también con las instancias de subclases de su tipo. Del mismo modo que es correcto asignar un byte a una variable declarada como int, se puede declarar que una variable es del tipo MiClase y guardar una referencia a una instancia de este tipo de clase:
MiPunto p;
Esta es una declaración de una variable p que es una referencia a un objeto de la clase MiPunto, de momento con un valor por defecto de null. La referencia null es una referencia a un objeto de la clase Object, y se podrá convertir a una referencia a cualquier otro objeto porque todos los objetos son hijos de la clase Object.
Constructores
Las clases pueden implementar un método especial llamado constructor. Un constructor es un método que inicia un objeto inmediatamente después de su creación. De esta forma nos evitamos el tener que iniciar las variables explícitamente para su iniciación.
El constructor tiene exactamente el mismo nombre de la clase que lo implementa; no puede haber ningún otro método que comparta su nombre con el de su clase. Una vez definido, se llamará automáticamente al constructor al crear un objeto de esa clase (al utilizar el operador new).
El constructor no devuelve ningún tipo, ni siquiera void. Su misión es iniciar todo estado interno de un objeto (sus atributos), haciendo que el objeto sea utilizable inmediatamente; reservando memoria para sus atributos, iniciando sus valores...
Por ejemplo:
MiPunto( ) {
 
  inicia( -1, -1 );
 
}
 
Este constructor denominado constructor por defecto, por no tener parámetros, establece el valor -1 a las variables de instancia x e y de los objetos que construya.
El compilador, por defecto ,llamará al constructor de la superclase Object() si no se especifican parámetros en el constructor.
Este otro constructor, sin embargo, recibe dos parámetros:
MiPunto( int paraX, int paraY ) {
 
  inicia( paramX, paramY );
 
}
 
La lista de parámetros especificada después del nombre de una clase en una sentencia new se utiliza para pasar parámetros al constructor.
Se llama al método constructor justo después de crear la instancia y antes de que new devuelva el control al punto de la llamada.
Así, cuando ejecutamos el siguiente programa:
MiPunto p1 = new MiPunto(10, 20);
System.out.println( "p1.- x = " + p1.x + " y = " + p1.y );
Se muestra en la pantalla:
p1.- x = 10 y = 20
Para crear un programa Java que contenga ese código, se debe de crear una clase que contenga un método main(). El intérprete java se ejecutará el método main de la clase que se le indique como parámetro.

El operador new
El operador new crea una instancia de una clase (objetos) y devuelve una referencia a ese objeto. Por ejemplo:
MiPunto p2 = new MiPunto(2,3);
Este es un ejemplo de la creación de una instancia de MiPunto, que es controlador por la referencia a objeto p2.
Hay una distinción crítica entre la forma de manipular los tipos simples y las clases en Java: Las referencias a objetos realmente no contienen a los objetos a los que referencian. De esta forma se pueden crear múltiples referencias al mismo objeto, como por ejemplo:
MiPunto p3 =p2;
Aunque tan sólo se creó un objeto MiPunto, hay dos variables (p2 y p3) que lo referencian. Cualquier cambio realizado en el objeto referenciado por p2 afectará al objeto referenciado por p3. La asignación de p2 a p3 no reserva memoria ni modifica el objeto.
De hecho, las asignaciones posteriores de p2 simplemente desengancharán p2 del objeto, sin afectarlo:
p2 = null; // p3 todavía apunta al objeto creado con new
Aunque se haya asignado null a p2, p3 todavía apunta al objeto creado por el operador new.
Cuando ya no haya ninguna variable que haga referencia a un objeto, Java reclama automáticamente la memoria utilizada por ese objeto, a lo que se denomina recogida de basura.
Cuando se realiza una instancia de una clase (mediante new) se reserva en la memoria un espacio para un conjunto de datos como el que definen los atributos de la clase que se indica en la instanciación. A este conjunto de variables se le denomina variables de instancia.
La potencia de las variables de instancia es que se obtiene un conjunto distinto de ellas cada vez que se crea un objeto nuevo. Es importante el comprender que cada objeto tiene su propia copia de las variables de instancia de su clase, por lo que los cambios sobre las variables de instancia de un objeto no tienen efecto sobre las variables de instancia de otro.
El siguiente programa crea dos objetos MiPunto y establece los valores de x e y de cada uno de ellos de manera independiente para mostrar que están realmente separados.
MiPunto p4 = new MiPunto( 10, 20 );
MiPunto p5 = new MiPunto( 42, 99 );
System.out.println("p4.- x = " + p4.x + " y = " + p4.y);
System.out.println("p5.- x = " + p5.x + " y = " + p5.y);
Este es el aspecto de salida cuando lo ejecutamos.
p4.- x = 10 y = 20
p5.- x = 42 y = 99

Acceso al objeto
El operador punto (.)
El operador punto (.) se utiliza para acceder a las variables de instancia y los métodos contenidos en un objeto, mediante su referencia a objeto:
referencia_a_objeto.nombre_de_variable_de_instancia
referencia_a_objeto.nombre_de_método( lista-de-parámetros );
Hemos creado un ejemplo completo que combina los operadores new y punto para crear un objeto MiPunto, almacenar algunos valores en él e imprimir sus valores finales:
MiPunto p6 = new MiPunto( 10, 20 );
System.out.println ("p6.- 1. X=" + p6.x + " , Y=" + p6.y);
p6.inicia( 30, 40 );
System.out.println ("p6.- 2. X=" + p6.x + " , Y=" + p6.y);
Cuando se ejecuta este programa, se observa la siguiente salida:
p6.- 1. X=10 , Y=20
p6.- 2. X=30 , Y=40
Durante las impresiones (método println()) se accede al valor de las variables mediante p6.x y p6.y, y entre una impresión y otra se llama al método inicia(), cambiando los valores de las variables de instancia.
Este es uno de los aspectos más importantes de la diferencia entre la programación orientada a objetos y la programación estructurada. Cuando se llama al método p6.inicia(), lo primero que se hace en el método es sustituir los nombres de los atributos de la clase por las correspondientes variables de instancia del objeto con que se ha llamado. Así por ejemplo x se convertirá en p6.x.
Si otros objetos llaman a inicia(), incluso si lo hacen de una manera concurrente, no se producen efectos laterales, ya que las variables de instancia sobre las que trabajan son distintas.

La referencia this
Java incluye un valor de referencia especial llamado this, que se utiliza dentro de cualquier método para referirse al objeto actual. El valor this se refiere al objeto sobre el que ha sido llamado el método actual. Se puede utilizar this siempre que se requiera una referencia a un objeto del tipo de una clase actual. Si hay dos objetos que utilicen el mismo código, seleccionados a través de otras instancias, cada uno tiene su propio valor único de this.
Un refinamiento habitual es que un constructor llame a otro para construir la instancia correctamente. El siguiente constructor llama al constructor parametrizado MiPunto(x,y) para terminar de iniciar la instancia:
MiPunto() {
 
  this( -1, -1 ); // Llama al constructor parametrizado
 
}
 
En Java se permite declarar variables locales, incluyendo parámetros formales de métodos, que se solapen con los nombres de las variables de instancia.
No se utilizan x e y como nombres de parámetro para el método inicia, porque ocultarían las variables de instancia x e y reales del ámbito del método. Si lo hubiésemos hecho, entonces x se hubiera referido al parámetro formal, ocultando la variable de instancia x:
void inicia2( int x, int y ) {
 
  x = x; // Ojo, no modificamos la variable de instancia!!!
 
  this.y = y; // Modificamos la variable de instancia!!!
 
}
La destrucción del objeto
La destrucción de los objetos
Cuando un objeto no va a ser utilizado, el espacio de memoria de dinámica que utiliza ha de ser liberado, así como los recursos que poseía, permitiendo al programa disponer de todos los recursos posibles. A esta acción se la da el nombre de destrucción del objeto.
En Java la destrucción se puede realizar de forma automática o de forma personalizada, en función de las características del objeto.
La destrucción por defecto: Recogida de basura
El intérprete de Java posee un sistema de recogida de basura, que por lo general permite que no nos preocupemos de liberar la memoria asignada explícitamente.
El recolector de basura será el encargado de liberar una zona de memoria dinámica que había sido reservada mediante el operador new, cuando el objeto ya no va a ser utilizado más durante el programa (por ejemplo, sale del ámbito de utilización, o no es referenciado nuevamente).
El sistema de recogida de basura se ejecuta periódicamente, buscando objetos que ya no estén referenciados.

La destrucción personalizada: finalize
A veces una clase mantiene un recurso que no es de Java como un descriptor de archivo o un tipo de letra del sistema de ventanas. En este caso sería acertado el utilizar la finalización explícita, para asegurar que dicho recurso se libera. Esto se hace mediante la destrucción personalizada, un sistema similar a los destructores de C++.
Para especificar una destrucción personalizada se añade un método a la clase con el nombre finalize:
class ClaseFinalizada{
 
  ClaseFinalizada() { // Constructor
 
    // Reserva del recurso no Java o recurso compartido
 
  }
 
  protected void finalize() {
 
    // Liberación del recurso no Java o recurso compartido
 
  }
 
}
 
El intérprete de Java llama al método finalize(), si existe cuando vaya a reclamar el espacio de ese objeto, mediante la recogida de basura.
Debe observarse que el método finalize() es de tipo protected void y por lo tanto deberá de sobreescribirse con este mismo tipo.
Programa de Ejemplo
En el siguiente ejemplo se crea una clase Coordenada que se encarga de mantener los dos datos y mostrarlos con las funciones analizadoras mostrarX y mostrarY. Esta clase tiene un constructor llamado Coordenada, que se encarga de inicializar las variables internas de la clase.
La clase Coordenada es llamada desde otra llamada verCoordenada, que constituye el programa principal de este ejemplo, esta segunda clase por esto debe contar con una funcion main.
La clase verCoordenada crea un objeto de tipo Coordenada llamado p1, y lo inicializa con los valores 3 y 5. Luego muestra por pantalla los contenidos que le devuelve el objeto p1 de clase Coordenada.
Observe que la inicializacion de la clase Coordenada en el objeto p1 se hace a través de una cláusula new, esta clausula se encarga de ejecutar el constructor de la clase (del mismo nombre), y por lo tanto es obligatorio pasarle los parametros que fueron definidos para él. Estos parametros estan definidos en el constructor Coordenada de la clase con el mismo nombre como (int x1, int y1). Por tanto se deben pasar dos parámetros enteros al inicializar el objeto que en este ejemplo son 3 y 5.
public class verCoordenada {
  public static void main (String args[]) {
    Coordenada p1;
    p1 = new Coordenada(3,5);
    System.out.println("("+p1.mostrarX()+","+p1.mostrarY()+")");
  }
}
 
class Coordenada {
  int x,y;
  // constructor
  Coordenada (int x1, int y1) {
    x=x1;
    y=y1;
  }
 
  // funciones de acceso a las variables
  public int mostrarX() {
    return x;
  }
  public int mostrarY() {
    return y;
  }
}
Ejecucion del programa
Esta es una aplicacion de escritorio en Java y se debe compilar igual que habiamos hecho en practicas anteriores. Luego de compilar deben crearse dos clases Coordenada.class y verCoordenada.class en el mismo directorio. Para ejecutar el programa debe usar verCoordenada.class, asi:
·         java verCoordenada
La salida del programa debe ser la siguiente:
(3,5)
Este programa lo que hace es simplemente guardar una coordenada y luego mostrarla. Lo importante est'a en crear un objeto y luego inicializarlo desde el programa principal.

No hay comentarios:

Publicar un comentario