Apuntes Lenguaje Java

20. Clases embebidas (Inner classes)

20.1 Concepto
20.2. Ejemplo

20.1 Concepto

Una clase embebida es una clase que se define dentro de otra. Es una característica de Java que permite agrupar clases lógicamente relacionadas y controlar la 'visibilidad' de una clase. El uso de las clases embebidas no es obvio y contienen detallas algo más complejos que escapan del ámbito de esta introducción.

Se puede definir una clase embebida de la siguiente forma:

class Externa {
    . . .
    class Interna {
        . . .
    }
}

La clase Externa puede instanciar y usar la clase Interna como cualquier otra, sin limitación ni cambio en la sintaxis de acceso:

class Externa {
    . . .
    class Interna {
        . . .
    }
    void metodo() {
        Interna i = new Interna(. . .);
        . . .
    }
}

Una diferencia importante es que un objeto de la clase embebida está relacionado siempre con un objeto de la clase que la envuelve, de tal forma que las instancias de la clase embebida deben ser creadas por una instancia de la clase que la envuelve. Desde el exterior estas referencias pueden manejarse, pero calificandolas completamente, es decir nombrando la clase externa y luego la interna. Además una instancia de la clase embebida tiene acceso a todos los datos miembros de la clase que la envuelve sin usar ningún calificador de acceso especial (como si le pertenecieran). Todo esto se ve en el ejemplo siguiente.

20.2. Ejemplo

Un ejemplo donde puede apreciarse fácilmente el uso de clases embebidas es el concepto de iterador. Un iterador es una clase diseñada para recorrer y devolver ordenadamente los elementos de algún tipo de contenedor de objetos. En el ejemplo se hace una implementación muy elemental que trabaja sobre un array.

class Almacen {
    private Object [] listaObjetos;
    private numElementos = 0;
    Almacen (int maxElementos) {
        listaObjetos = new Object[maxElementos];
    }
    public Object get(int i) {
        return listaObject[i];
    }
    public void add(Object obj) {
        listaObjetos[numElementos++] = obj;
    }
    public Iterador getIterador() {
        new Iterador();
    }
    
    class Iterador {
        int indice = 0;
        Object siguiente() {
            if (indice < numElementos) return listaObjetos[indice++];
            else return null;
        }
    }
}

Y la forma de usarse, sería:

Almacen alm = new Almacen(10); // se crea un nuevo almacen
. . .
alm.add(...);    // se añaden objetos
. . .
// para recorrerlo
Almacen.Iterador i = alm.getIterador(); // obtengo un iterador para alm
Object o;
while ( (o = i.siguiente()) != null) {
    . . .
}

Antonio Bel Puchol - antonio@abelp.net