InicioInicio BlogBlog portfolioCurriculum ProyectosProyectos videoLinks MyIpodMyIpod calendarContacto rssRSS

Introducción
Una de las características más interesantes de java son las clases internas.  Una de los principios de la OOP (Programación Orientada a Objetos) es  el concepto de “caja negra”, el cual define que la implementación debe estar oculta y controlada para  un “cliente” (entiéndase como otra aplicación, una clase, una persona etc.).
Como habrán de saber dentro de una clase normal podemos declarar métodos, propiedades y atributos privados para evitar el acceso a terceros, en algunos lenguajes permiten contener clases.
Estas clases tienen acceso a las propiedades y métodos de su clase contenedora es “casi” (ojo las comillas) a una herencia.

En este post trataremos estos temas
Clases Internas
Clases internas dentro de un método
Clases anónimas

Clases Internas

package innerclasstest;
public class Main {
	private class MyInnerClass
	{
		private String label;
 
		public MyInnerClass(String label)
		{
			this.label=label;
		}
		public MyInnerClass()
		{
			this.label="Soy un constructor sin parametros :(";
 
		}
 
		public void printLabel()
		{
			System.out.println(this.label);
		}
	}
	public Main()
	{
		MyInnerClass uno=new MyInnerClass("Soy un constructor con parametros");
		MyInnerClass dos=new MyInnerClass();
		uno.printLabel();
		dos.printLabel();
 
	}
	public static void main(String[] args) {
		Main test=new Main();
 
	}
}

En el ejemplo anterior notamos tres puntos importates.
La clase interna (MyInnerClass) se declara exactamente como cualquier otra clase
Se instancia como cualquier otra clase dentro de la clase contenedora.
Puede declararse como privada, publica o protegida.

Como se ha mencionado puede llamar a los elementos de la clase contenedora aunque sean declarados como privados, para hacer la llamada tenemos que hacerlo de la siguiente manera: NombredelaClaseContenedora.this.nombreMetodoOPropiedad.
Seria algo como asi,

package innerclasstest;
public class Main {
	/*Clase Interna*/
	private class MyInnerClass
	{
 
        		public void callToCall(String parametro)
        		{
           		          Main.this.call(parametro);/*OJO la llamada*/
            }
	}
	/*Fin de la clase Interna*/
 private void call(String parametro)
    	{
        		System.out.println(parametro);
}
 
	public Main()
	{
MyInnerClass test=new MyInnerClass();
            uno.callToCall("Estoy Llamando un metodo de la clase contenedora");
}
	public static void main(String[] args) {
		Main test=new Main();
 
	}
}

Como vemos call(String parametro) es privado pero es facilmente llamado por la clase interna

Clases internas dentro de un método

Como hemos visto una clase puede contener una clase, pero dentro de java podemos declarar una clase dentro de una método, en este ciclo de vida de la clase depende de la ejecución del método, o en todo caso dependerá de cuanto dure el bloque donde estara declarada la clase, antes o después del bloque la clase no existe por ende no puede ser instanciada, un ejemplo seria algo asi

package innerclasstest;
public class Main {
 
    public void ContrustruirUnaClase()
    {
        class Metodo
        {
            public void print(){System.out.println("hola mundo");};
        }
        new Metodo().print();
    }
 
	public Main()
	{
        this.ContrustruirUnaClase();
	}
	public static void main(String[] args) {
		Main test=new Main();
 
	}
}

Aunque seria un uso poco común el anterior ejemplo, y la verdad no tendría sentido, el uso mas común de contener una clase dentro de un método seria retornar una instancia de esta clase. Para esto necesitamos que nuestra clase interna herede una clase (ya sea abstracta o sencilla) o implemente una interfaz. El codigo de la interfaz y la clase abstracta seria algo como así.

abstract class  AbstractClass {
    protected int res=0;
 
    public  abstract void addToSum(int b);
 
    public int getRes() {
        return res;
    }
}

Y el de la interfaz

public interface IInterface {
 
    int Sum(int b,int c);
}

Ahora veamos como seria la implementación y una prueba, cabe destacar que este tipo de implementación facilita el patrón de fabrica abstracta

package innerclasstest;
public class Main {
 
    public IInterface getInstance()
    {
        class test implements IInterface
        {
            public int Sum(int b, int c) {
                return b+c;
            }
        }
        return new test();
    }
 
    public AbstractClass getInstanceAbstract()
    {
        class test extends AbstractClass
        {
 
            @Override
            public void addToSum(int b) {
                super.res+=b;
            }
 
        }
        return new test();
    }
 
	public static void main(String[] args) {
		Main test=new Main();
       		Interface test2=test.getInstance();
         	System.out.println(test2.Sum(3, 5));
        	AbstractClass test3=test.getInstanceAbstract();
            test3.addToSum(5);
            test3.addToSum(10);
            test3.addToSum(11);
            System.out.println(test3.getRes());
	}
}

Clases anónimas

Como hemos visto las clases internas tiene una utilidad bastante evidente, sobre todo en la capacidad que tienen de ocultar código, a las programadores que usan la herramienta NetBeans notaran que cuando este genera un JFrame genera un main y dentro del main incluye unas lineas parecidas a esta

  java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new NewJFrame().setVisible(true);
            }
        });

Como vemos este realiza un new Runnable(), pero Runnable es una interfaz y aparte de esto desarrolla un cuerpo e implementa el método run(), en java se permite este tipo de instrucciones lo cual esta clase que implementa Runnable se le conoce como una clase anónima, la cual no posee un nombre, pero se sabe que implementa o extiende de una interfaz o una clase, por lo cual se le puede hacer un upcasting. Ahora del ejemplo del subtema anterior usaremos la clase abstracta AbstractClass y la interfaz IInterface, Ahora retornaremos usando una clase anónima dentro de la estructura de los métodos

 package innerclasstest;
public class Main {
        public AbstractClass getInstanceAbstractTwo()
    {
        return new AbstractClass(){
 
            @Override
            public void addToSum(int b) {
               super.res+=b;
            }
        };
    }
 
    public IInterface getInstanceTwo()
    {
        return new IInterface()
        {
            public int Sum(int b, int c) {
                return b+c;
            }
        };
    }
 
	public static void main(String[] args) {
		Main test=new Main();
 
        AbstractClass test4=test.getInstanceAbstractTwo();
        test4.addToSum(10);
        test4.addToSum(11);
        test4.addToSum(12);
        System.out.println(test4.getRes());
 
        IInterface test5=test.getInstanceTwo();
        System.out.println(test5.Sum(10, 21));
	}
}

Como vemos es una manera abreviada de retornar una clase implementada en el cuerpo de un método. Una desventaja de este método es que al no tener una clase con un nombre el compilador no permitirá sobrecargar el constructor vacio, para esto deberemos declarar un bloque sin nombre y definir los parámetros en el metodo contenedor como final, ya que los parámetros tienen que existir para ser llamados en el bloque vació. Por inconveniente el constructor no puede ser sobrecargado y no puede existir más de un constructor. Un ejemplo seria esto.

package innerclasstest;
public class Main {
 
    public IInterface getInstanceTwo(final int b,final int c)
    {
        return new IInterface()
        {
            private int k;
            private int l;
            {
                this.k=b;
                this.l=c;
            }
 
            public int Sum(int b, int c) {
                return k+l+c+b;
            }
 
        };
    }
 
	public Main()
	public static void main(String[] args) {
Main test=new Main();
           IInterface test6=test.getInstanceTwo(10, 20);
           System.out.println(test6.Sum(10, 21));
	}
}

En un futuro post trataremos instanciar clases internas en otras clases y clases internas dentro de clases abstractas e interfaces.

codigo de ejemplo


5 comentarios a “Introducción a InnerClass en Java I”  

  1. 1 Alicia Estrada

    interesante, me ayudo muchooo!!!!

  2. 2 mio

    esto no entiendo aselo mas sencillo

  3. 3 admin

    mio con mucho gusto, solamente podrias decirme como que nivel de conocimientos de java tenes para poder acomodar un ejemplo

  4. 4 Eduardo

    Amigo muchos gracias voy a seguir este ejemplo ta buenisimo ^^

  5. 5 Eduardo

    Sos un trome man ^^ me has ayudado un monton :D !!

Deja una respuesta



Categorías

Contacto

RSS Polygonize

Directorio de enlaces

Comparte este artículo

 
kajsdlkhsd