Acabo de encontrar una interfaz anidada estática en nuestra base de código.
class Foo {
public static interface Bar {
/* snip */
}
/* snip */
}
Nunca he visto esto antes. El desarrollador original está fuera de alcance. Por lo tanto, tengo que preguntar SO:
¿Cuáles son las semánticas detrás de una interfaz estática? ¿Qué cambiaría si elimino el static
? ¿Por qué alguien haría esto?
Respuestas:
La palabra clave estática en el ejemplo anterior es redundante (una interfaz anidada es automáticamente "estática") y se puede eliminar sin ningún efecto en la semántica; Recomendaría que se elimine. Lo mismo ocurre con "público" en los métodos de interfaz y "público final" en los campos de interfaz: los modificadores son redundantes y simplemente agregan desorden al código fuente.
De cualquier manera, el desarrollador simplemente declara una interfaz llamada Foo.Bar. No hay más asociación con la clase que lo encierra, excepto que el código que no puede acceder a Foo tampoco podrá acceder a Foo.Bar. (Desde el código fuente: ¡el bytecode o la reflexión pueden acceder a Foo.Bar incluso si Foo es un paquete privado!)
Es un estilo aceptable crear una interfaz anidada de esta manera si espera que se use solo desde la clase externa, de modo que no cree un nuevo nombre de nivel superior. Por ejemplo:
fuente
La pregunta ha sido respondida, pero una buena razón para usar una interfaz anidada es si su función está directamente relacionada con la clase en la que se encuentra. Un buen ejemplo de esto es a
Listener
. Si tuviera una claseFoo
y quisiera que otras clases pudieran escuchar eventos en ella, podría declarar una interfaz llamadaFooListener
, que está bien, pero probablemente sería más claro declarar una interfaz anidada e implementar esas otras clasesFoo.Listener
( una clase anidadaFoo.Event
no es mala junto con esto).fuente
java.util.Map.Entry
(que es una interfaz anidada en otra interfaz).Map.Entry
) o las clases también estén dentro de ese paquete. Digo esto porque me gusta mantener mis clases cortas y al grano. También un lector puede ver qué otras entidades están relacionadas con una clase mirando las clases en el paquete. Probablemente tendría un paquetejava.collections.map
para mapas. Se trata de OO y modularidad.java.util
tiene demasiadoutil
es comocommon
- un olor IMOjava.util
ciertamente tiene demasiado. Dicho esto, tampoco creo que sea ideal dividirlo en paquetes tan finos como sugieres.java.util.MapEntry
fuera de su propio paquete. Primer reflejo: ¿cuáles son las interfaces relacionadas con esta clase? Miro a la clase. A menos que javadoc se vincule a esta interfaz, no tengo idea de su relación. Además, las personas no miran el paquete de importación. Todos tienen sus propias opiniones. Nadie tiene razón, nadie está equivocadoLas interfaces de los miembros son implícitamente estáticas. El modificador estático en su ejemplo se puede eliminar sin cambiar la semántica del código. Consulte también la Especificación del lenguaje Java 8.5.1. Declaraciones de tipo de miembro estático
fuente
Una interfaz interna tiene que ser estática para poder acceder. La interfaz no está asociada con instancias de la clase, sino con la clase misma, por lo que se accedería de esta
Foo.Bar
manera:En la mayoría de los casos, esto no es diferente de una clase interna estática.
fuente
The interface isn't associated with instances of the class, but with the class itself
más, no lo entendíLa respuesta de Jesse es cercana, pero creo que hay un mejor código para demostrar por qué una interfaz interna puede ser útil. Mire el código a continuación antes de seguir leyendo. ¿Puedes encontrar por qué la interfaz interna es útil? La respuesta es que la clase DoSomethingAlready se puede instanciar con cualquier clase que implemente A y C; no solo la clase concreta Zoo. Por supuesto, esto se puede lograr incluso si AC no es interno, pero imagine concatenar nombres más largos (no solo A y C), y haciendo esto para otras combinaciones (digamos, A y B, C y B, etc.) y usted fácilmente ver cómo las cosas se salen de control. Sin mencionar que las personas que revisan su árbol de origen se verán abrumadas por las interfaces que son significativas solo en una clase.Una interfaz interna permite la construcción de tipos personalizados y mejora su encapsulación .
fuente
Zoo
no no implementa la interfazAC
, por lo tanto, los casos deZoo
lata no pueden pasar al constructor deDoSomethingAlready
que esperaAC
. El hecho de queAC
extienda ambos,A
yC
, no implica que las clases se implementenA
yC
mágicamente también se implementenAC
.Para responder su pregunta muy directamente, mire Map.Entry.
Map.Entry
También esto puede ser útil
Entrada de blog de Inerfaces anidadas estáticas
fuente
Típicamente veo clases internas estáticas. Las clases internas estáticas no pueden hacer referencia a las clases que contienen, mientras que las clases no estáticas sí. A menos que se encuentre con algunas colisiones de paquetes (ya hay una interfaz llamada Bar en el mismo paquete que Foo), creo que lo convertiría en su propio archivo. También podría ser una decisión de diseño para imponer la conexión lógica entre Foo y Bar. Quizás el autor pretendía que Bar solo se usara con Foo (aunque una interfaz interna estática no impondrá esto, solo una conexión lógica)
fuente
Si cambia la clase Foo a la interfaz Foo, la palabra clave "pública" en el ejemplo anterior también será redundante porque
fuente
En 1998, Philip Wadler sugirió una diferencia entre interfaces estáticas e interfaces no estáticas.
Por ejemplo, propuso una solución al problema de expresión , que es el desajuste entre la expresión como "cuánto puede expresar su idioma" por un lado y la expresión como "los términos que está tratando de representar en su idioma" por otro lado .
Un ejemplo de la diferencia entre interfaces anidadas estáticas y no estáticas se puede ver en su código de muestra :
Su sugerencia nunca lo hizo en Java 1.5.0. Por lo tanto, todas las demás respuestas son correctas: no hay diferencia en las interfaces anidadas estáticas y no estáticas.
fuente
En Java, la interfaz / clase estática permite que la interfaz / clase se use como una clase de nivel superior, es decir, puede ser declarada por otras clases. Entonces, puedes hacer:
Sin la estática, lo anterior no se podría compilar. La ventaja de esto es que no necesita un nuevo archivo fuente solo para declarar la interfaz. También asocia visualmente la barra de interfaz a la clase Foo, ya que debe escribir Foo.Bar e implica que la clase Foo hace algo con instancias de Foo.Bar.
Una descripción de los tipos de clase en Java .
fuente
Estático significa que cualquier parte de la clase del paquete (proyecto) puede acceder a él sin usar un puntero. Esto puede ser útil u obstaculizar dependiendo de la situación.
El ejemplo perfecto de las líneas útiles de los métodos "estáticos" es la clase Math. Todos los métodos en matemáticas son estáticos. Esto significa que no tiene que salir de su camino, hacer una nueva instancia, declarar variables y almacenarlas en aún más variables, solo puede ingresar sus datos y obtener un resultado.
La estática no siempre es tan útil. Si está haciendo una comparación de casos, por ejemplo, es posible que desee almacenar datos de varias maneras diferentes. No puede crear tres métodos estáticos con firmas idénticas. Necesita 3 instancias diferentes, no estáticas, y luego puede y comparar, porque si es estático, los datos no cambiarán junto con la entrada.
Los métodos estáticos son buenos para devoluciones únicas y cálculos rápidos o datos fáciles de obtener.
fuente