Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Clases anidadas
• Hay muchas situaciones en las que la existencia de los objetos de una clase
se justifica únicamente por la existencia de objetos de otra clase (eg. los
nodos de una lista enlazada y los iteradores sobre dicha lista).
• En otros casos, es conveniente dotar a algunos objetos de un contexto global
Laboratorio de Programación III común (algo parecido a lo que ocurre con los ámbitos léxicos en lenguajes
como Pascal). Esta situación ocurre, por ejemplo, con los manejadores de
Curso 2001 - 2002 eventos en interfaces gráficas (precisan de un contexto global común a
Profesor: José Luis Sierra través del cuál comunicarse fácilmente).
• En todas estas situaciones es conveniente, además, relajar los criterios de
accesibilidad para estas clases estrechamente relacionadas (algo parecido a
lo que ocurre con las clases amigas en C++).
• Java proporciona un mecanismo para tratar con todas estas situaciones: las
clases anidadas.
3 4
Clases anidadas estáticas Clases anidadas estáticas
• Este uso permite concebir las clases contenedoras como módulos que class Aritmetica
class Aritmetica {{
public interface
interface Expresion
Expresion {{
encapsulan las clases internas. public
double evalua();
evalua();
double
• Esta es la única forma de controlar realmente el uso de una clase: si }}
una clase interna estática se declara privada, únicamente podrá ser abstract protected
abstract protected static
static class
protected Expresion
Expresion op1;
class ExpresionBinaria
op1;
ExpresionBinaria implements
implements Expresion{
Expresion{
5 6
class Operaciones
class Operaciones extends
extends Aritmetica
Aritmetica {{
public static
public static class
class Suma
Suma extends
extends ExpresionBinaria
ExpresionBinaria {{ public static
static void
void main(String[]
main(String[] args)
args) {{
public
public Suma(Expresion
public Suma(Expresion op1,
op1, Expresion
Expresion op2)
op2) {{ Aritmetica.Expresion ee ==
Aritmetica.Expresion
super(op1,op2);
super(op1,op2); new Operaciones.Suma(
Operaciones.Suma(
new
}} new Operaciones.Neg(new
new Operaciones.Neg(new Operaciones.Num(5)),
Operaciones.Num(5)),
public double
public double evalua()
evalua() {{ new Operaciones.Num(6));
Operaciones.Num(6));
new
return op1.evalua()
return op1.evalua() ++ op2.evalua();
op2.evalua(); System.out.println(e.evalua());
System.out.println(e.evalua());
}} }}
}}
public static
public static class
class Neg
Neg extends
extends ExpresionUnaria
ExpresionUnaria {{
public Neg(Expresion
public Neg(Expresion op)op) {{
super(op);
super(op);
}}
public double
public double evalua()
evalua() {{
return -- op.evalua();
return op.evalua();
}}
}}
...
...
}}
7 8
Clases Internas Clases Internas
interface Enumeration
interface Enumeration {{
• Las instancias de las clases internas (clases anidadas no estáticas) sólo public boolean
public boolean hasMoreElements();
hasMoreElements();
tienen sentido en el contexto de las instancias de las clases contenedoras. public Object
public Object nextElement();
nextElement();
}}
Objeto contenedor public class
class Stack
Stack {{
public
private Vector
private Vector items;
items;
Objeto interno Esta clase permite adaptar
...//código para
...//código para la
la pila
pila ...
... Stack a la interfaz
• Desde las clases internas son visibles todos los miembros de la clase Enumeration. Si Stack
public Enumeration
Enumeration enumerator()
enumerator() {{ implementara directamente
contenedora (independientemente de sus modificadores). public
return new
return new StackEnum();
StackEnum(); Enumeration, no podría
• Una clase interna no puede tener (y no tiene sentido que tenga) miembros }} tenerse simultáneamente
estáticos. private class
private class StackEnum
StackEnum implements
implements Enumeration
Enumeration {{ múltiples iteradores sobre
int currentItem
currentItem == items.size()
items.size() -- 1;
1; las pilas.
• Cuando una clase interna se declara dentro de un método (esto tiene, sobre int
public boolean
boolean hasMoreElements()
hasMoreElements() {{
public
todo, sentido para las clases anónimas), dentro de la clase puede verse return (currentItem
(currentItem >=
>= 0);
0);
return
también variables locales del método, pero éstas tienen que haber sido }}
declaradas finales, y se han debido inicializar antes de su uso en la clase public Object
public Object nextElement()
nextElement() {{
interna. if (!hasMoreElements())
if (!hasMoreElements()) throw
throw new
new NoSuchElementException();
NoSuchElementException();
else return
return items.elementAt(currentItem--);
items.elementAt(currentItem--);
• Las clases internas son especialmente útiles para implementar adaptadores }}}
else
(clases que permiten a otra clase ajustarse a una interfaz). 9 }}} 10
13 14
public class
public class Stack
Stack {{
private Vector
private Vector items;
items; interface Lambda
interface Lambda {{
Object aplica(Object
Object aplica(Object valor);
valor);
...//código para
para la
la pila
pila ...
...
...//código Creación de una }}
public Enumeration
Enumeration enumerator()
enumerator() {{ instancia de una clase
public
return new
new Enumeration()
Enumeration() {{ anónima que
return abstract class
class UtilidadesLista
UtilidadesLista {{
int currentItem
int currentItem == items.size()
items.size() -- 1;
1; implementa la interfaz abstract
public boolean
boolean hasMoreElements()
hasMoreElements() {{ Enumertation abstract protected
abstract protected List
List creaLista();
creaLista();
public
return (currentItem
return (currentItem >=
>= 0);
0); ...
...
}} public List
public List map(List
map(List l,Lambda
l,Lambda f)
f) {{
public Object
public Object nextElement()
nextElement() {{ List res
res == creaLista();
creaLista();
if (!hasMoreElements())
(!hasMoreElements()) List
if for (int
(int i=0;
i=0; ii << l.size();
l.size(); i++)
i++)
throw new
new NoSuchElementException();
NoSuchElementException(); for
throw res.add(i,f.aplica(l.get(i)));
else return
else return items.elementAt(currentItem--);
items.elementAt(currentItem--); res.add(i,f.aplica(l.get(i)));
}}; return res;
return res;
}};
}} }}
}} ...
...
}}
15 16
Clases Anónimas Clases Anónimas
...
Ejemplos de algunos usos comunes de clases anónimas en
...
// numeros
// numeros es
es una
una lista
lista que
que contiene
contiene objetos
objetos dede tipo
tipo Integer.
Integer. interfaces gráficas.
List incrementada
List incrementada ==
...
...
new UtilidadesLista()
new UtilidadesLista() {{
JButton exit
JButton exit == new
new JButton("exit");
JButton("exit");
protected List
protected List creaLista()
creaLista() {{
exit.addActionListener(
exit.addActionListener(
return new
return new ArrayList();
ArrayList();
new ActionListener()
new ActionListener() {{
}} public void
void actionPerformed(ActionEvent
actionPerformed(ActionEvent ev)
ev) {{
}.map(numeros, public
}.map(numeros, System.exit(0);
new Lambda()
Lambda() {{ System.exit(0);
new }});
public Object
Object aplica(Object
aplica(Object v)v) {{ }});
public ...
return new
new Integer(((Integer)
Integer(((Integer) v).intValue()+1);
v).intValue()+1); ...
return JFrame ff == new
new JFrame();
JFrame();
JFrame
}} f.addWindowListener(
}); f.addWindowListener(
}); new WindowAdapter()
WindowAdapter() {{
new
public void
public void windowClosing(WindowEvent
windowClosing(WindowEvent ev)
ev) {{
System.exit(0);
System.exit(0);
}});
}});
...
...
17 18