que - iterator() java
¿Por qué la interfaz del iterador de Java debería implementarse como clase interna? (5)
Fundamentalmente, un iterador es con estado: necesita saber hacia dónde apunta dentro de la colección. Eso no pertenece como parte de la colección en sí, y la explicación dada es la correcta ... es muy posible tener dos objetos iteradores independientes, iterando sobre el mismo objeto de colección. ¿Cómo modelaría eso si la colección misma implementara la interfaz Iterator? Es posible (por ejemplo, crear una nueva instancia de la colección que a su vez tenía una referencia a la colección original), pero sería realmente feo.
Aquí hay preocupaciones separadas:
- La recopilación de datos
- Un cursor colocado dentro de la colección
Preocupaciones separadas => clases separadas.
La forma más simple de persuadirse de esto es probablemente intentar implementar su propia colección, y luego tener múltiples iteradores. Por ejemplo, puede intentar:
List<String> foo = new MyListImplementation<String>();
foo.add("a");
foo.add("b");
// The enhanced for loop uses Iterable/Iterator for non-arrays
for (String x : foo) {
for (String y : foo) {
System.out.println(x + " " + y);
}
}
Eso debería imprimir:
a a
a b
b a
b b
Intente implementarlo sin tener dos clases, y vea cómo lo hace, teniendo en mente la separación de las preocupaciones.
Hace poco leí un libro "The Java Tutorials" 3ª edición. Habla sobre la implementación de clase interna como lo muestra la imagen.
En el 3er párrafo, dice "La clase Stack en sí no debería implementar la interfaz Iterator, porque ...".
No puedo encontrar ningún motivo por el que la clase Stack no deba implementar Iterator. La razón dada NO es persuasiva.
¿Podrías explicarlo?
Hay 2 razones por las que puedo pensar en mi cabeza.
Múltiples tipos de iteradores
Es posible que desee varios tipos de iteradores que iteren de diferentes maneras. Por ejemplo, tanto un iterador directo como un iterador inverso (itera desde el final del contenedor hasta el comienzo).
Varias instancias de iteradores
Si tiene un algoritmo de pase múltiple y / o bucles anidados, cada bucle puede querer su propio iterador que realiza un seguimiento de dónde está en el contenedor, independientemente de los otros iteradores.
Sería difícil, si no imposible, respaldar estas funcionalidades con la interfaz Iterator
implementada en la clase Stack
.
La pila no debería implementar el iterador en sí mismo porque entonces podría tener solo un iterador a la vez, y al iterar sobre una pila se cambiaría la pila.
Para este último problema, observe que la clase anidada tiene un campo "currentItem". Este campo debería estar en "Pila", y cambiaría cuando se invoca a next (). Iterando sobre una colección no debería cambiar la colección.
El primer problema es más serio: supongamos que dos personas iteran sobre la pila (o un método desea crear dos iteradores sobre la pila). Entonces, si iterator()
devolviera this
, los dos iteradores serían lo mismo. Llamar a next()
en una movería la otra. Caos.
Solo para agregar a la discusión, la clase interna tendrá acceso a datos privados de la clase Stack, para que de esta manera, la clase Stack logre manejar el programador cliente un objeto, o múltiples objetos (el iterador (es), y aún estos objetos podrán acceder a la clase y proporcionar una iteración separada sobre la colección.
Una Stack
no puede ser su propio Iterator
porque una pila admite más de un iterador.
Es posible que desee iterar sobre la pila más de una vez. Estas iteraciones pueden ocurrir en diferentes momentos, o incluso al mismo tiempo. Múltiples iteraciones al mismo tiempo requieren claramente múltiples objetos. Varias iteraciones en diferentes momentos requieren múltiples objetos porque la interfaz del iterador no admite regresar al inicio.