Pregunta ¿Por qué la interfaz del iterador de Java debería implementarse como clase interna?


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?

Inner class Inner class


9
2018-04-18 16:52


origen


Respuestas:


Fundamentalmente, un iterador es con estado: necesita saber dónde está apuntando 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? Sus posible (por ejemplo, creando 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);
    }
}

Ese 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.


9
2018-04-18 16:56



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 sí iterator() devuelto this, los dos iteradores serían la misma cosa. Vocación next() en una movería la otra. Caos.


4
2018-04-18 16:58



UN 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.


2
2018-04-18 16:55



Hay 2 razones por las que puedo pensar en mi cabeza.

Múltiple 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).

Múltiple 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 el Iterator interfaz implementada en el Stack clase.


1
2018-04-18 16:59



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.


0
2018-03-31 21:10



Preguntas populares