jueves, 6 de junio de 2013

Clases Anidadas

Buenas amigos en este nuevo tema vamos a hablar de las clases anidadas. En java es posible crear una clase dentro de otra clase, o crear una clase dentro de un método, o incluso crear clases sin nombre. Esto a veces y bien visto, nos permite en gran manera hacer paquetes más compactos, un código más legible y en general nos permite agilizar más la cosa. Veamoslo.



La verdad sea dicha, he leído algunos libros sobre programación java y he visto incontables tutoriales de todo tipo en la red, y no hay ninguno que ponga en número de tipos diferentes que tiene, en unos sitios he leído 5 tipos, en otros 3, en otros 2 y diferentes subtipos...pero en realidad son todo lo mismo, así que yo voy a rizar el rizo y lo voy a explicar lo más fácilmente posible, a mi entender. Los tipos de clases internas son:

          • Estáticas Internas.
          • No-Estáticas Internas:
            1. Internas Miembro
            2. Internas de Método
            3. Internas Anónimas.
Estáticas Internas:

Este tipo de clase interna tiene las siguientes normas:
    • Se declaran igual que una clase normal, con la diferencia de que le añadimos la palabra reservada "static" a la clase
      • static class NombreClase{}
    • Pueden acceder a métodos y variables de la clase "externa" directamente, siempre que estos sean estáticos(incluidos privados).
    • En caso de que los atributos o métodos no sean estáticos, podemos seguir accediendo a ellos, pero deberemos de instanciar su clase (crear un objeto de la clase).
    • Para crear una instancia de la clase estática interna lo haremos de la siguiente manera:
      • ClaseExterna.ClaseEstaticaInterna nombre=new ClaseExterna.ClaseEstaticaInterna();
Veamos un ejemplo:


Tenemos una clase A con una clase estática B. Podéis observar que la clase estática B tiene un constructor(¿por que no iba a tenerlo si es una clase?) y en ese constructor imprimo por pantalla los dos valores que tengo, uno estático y otro no-estático, aunque para el no-estático he tenido que instanciar la clase externa (A), sigo pudiendo acceder al atributo "a". Luego en la MAIN, como veis creo un objeto, que realmente no hace nada es solo para que lo veáis, y al crearlo ejecuto el constructor de la clase B.

Clase Interna Miembro:

La Clase Interna Miembro tiene las siguientes normas:
    • Este tipo de clases es considerado un elemento más de la clase externa, con lo cual puede tener libre acceso a métodos y atributos de su clase externa (incluso privados).
    • No podemos definir variables ni métodos estáticos dentro de este tipo de clases, a no ser que sea alguna variable de tipo constante.
    • Se declara como una clase normal
      • class ClaseInterna{};
    • Para acceder a métodos y atributos de esta clase interna desde la clase externa deberemos de instanciar la clase Interna.
      • ClaseExterna.ClaseEstaticaInterna nombre=new ClaseExterna.ClaseEstaticaInterna();
Veamos un ejemplo:



Bien, como ya dijimos, este tipo de clases se comportan como un miembro más de la clase y como tal, al no ser un miembro estático no podemos invocarlo directamente en el método "estático" MAIN. Si yo hiciese lo siguiente:

  • A.B ab=new A.B();
Eclipse se inmolaría directamente, por esa razón he creado en el constructor de A dos formas de acceder al método de B, y ambas son validas:
  1. La primera sería creando una instancia de B y llamar a su método directamente. Esta forma es la que haríamos en caso de que quisiéramos acceder al método de B desde la clase A.
  2. La segunda sería instanciando la clase B desde A y así poder llamar a su método. Cabe decir que esta segunda forma sería la que utilizásemos en caso de encontrarnos en una clase distinta a A.
Por lo demás todo bien, tenemos una clase con un método el cual puede acceder a cualquier atributo o método ya sea privado o no.

Clases Internas de Método:

Bien para seguir el funcionamiento de este tipo de clase seguiremos las siguientes normas:
      • La clase solo podrá ser instanciada dentro del mismo método.
      • Una clase interna a método puede acceder a las variables locales del método SOLO si son  FINAL, pero puede acceder con normalidad al resto de variables de la clase.
      • Los modificadores permitidos por este tipo de clase son "abstract" y "final".


Como veis tengo una clase A con 2 atributos, uno estático y otro no-estático..
Creo un método en la clase A que contiene una variable local final y una clase interna B, la cual tiene un método que imprime por pantalla el atributo no-estático "a", el atributo estático "b" y la variable local final "x". Posteriormente instancio la clase B en el mismo método y llamo a "otroMetodo()" para que me imprima.
Veréis que no hay ningún problema en acceder a atributos de la clase externa, en cambio para acceder a los del método, estos deben ser "final".

Clases Internas Anónimas:

Las siguientes reglas a seguir con este tipo de clases son:
  • Siempre debe ser una subclase de otra clase ya existente o bien, implementar alguna interfaz.
    • ClasePadre cp=new ClasePadre(){ //Definición de la clase anónima...};
  • La definición de la clase anónima se lleva en una linea de código, por lo tanto se debe añadir punto y coma ";" al final de la declaración.
  • Solamente podrá acceder a los métodos de la clase que se hayan heredado, sobrescrito o implementado.
  • Es posible encontrarse una clase anónima como argumento de un método.

Bien, para este caso he variado un poco para que podáis observarlo más claramente.
Creamos una instancia de la clase Thread a la cual le pasamos por constructor un objeto que implemente la interfaz Runnable, en temas anteriores hablamos de los hilos, y recordar que había dos formas de crearlos:
  1. Heredando la clase Thread
  2. Implementando la interfaz Runnable.
Cuando implementábamos Runnable, debíamos de crear un objeto de Thread y pasarlo por argumentos. Ahora, en este ejemplo, veis que le paso directamente una clase anónima la cual me sobrescribe el método run. Con esto nos ahorramos el crear una clase. Las clases anónimas las veréis sobre todo para hilos y capturar eventos, son muy muy útiles.

Bueno amigos, ha sido todo un placer.

Un saludo.



    8 comentarios:

    1. Bartolomé felicidades por el post, claro, breve y sencillo.

      ResponderEliminar
    2. Excelente Post!!!
      Una duda estos ejemplos los podemos igualar o comparar con Asociacion de UML

      ResponderEliminar
    3. muy bueno el material... Gracias....!!!!

      ResponderEliminar
    4. ¡Muchas gracias! Bonito, sencillo y claro.

      ResponderEliminar
    5. Me sirvio mucho, estaba claro y sencillo

      ResponderEliminar