2011-11-03 19 views
19

I.e. ¿Por qué la siguiente "dependencia cíclica" no es posible?¿Por qué Java prohíbe la herencia de interfaces internas?

public class Something implements Behavior { 
    public interface Behavior { 
     // ... 
    } 
} 

Como las interfaces no hacen referencia a la clase externa, esto debería permitirse; sin embargo, el compilador me obliga a definir esas interfaces fuera de la clase. ¿Hay alguna explicación lógica para este comportamiento?

+0

Parece que el cargador de clases debería leer la clase primero para conocer la interfaz que necesita para definir la clase en primer lugar ... No conozco los detalles de la carga de clases, pero parece bastante obvio. –

+2

@donneo: dado que el compilador se queja de una "dependencia cíclica", imagino que ya sabe qué tipos se definen en la clase interna. Simplemente parece una restricción arbitraria para mí. –

+0

@PhilipK: ¿qué compilador estás usando? Los míos (Oracle JDK 6 y 7) solo se quejan de que "no pueden encontrar el símbolo". Aparte de eso: buena pregunta, ya que una interfaz anidada realmente * no confía * en la clase externa de ninguna manera técnica, esto * podría * ser legal. –

Respuesta

11

normas pertinentes en spec:

http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.4

Una clase C depende directamente de un tipo T si T se menciona en el extiende o implementa cláusula de C, ya sea como una superclase o superinterfaz o como un calificador de una superclase o nombre de superinterfaz.

http://java.sun.com/docs/books/jls/third_edition/html/interfaces.html#9.1.3

Una interfaz I depende directamente de un tipo T si T es mencionado en la cláusula extiende de I sea como un superinterfaz o como un calificador dentro de un nombre superinterfaz.

Por lo tanto, si A extends|implements B.C, A depende tanto C y B. Spec luego prohíbe las dependencias circulares.

La motivación de incluir B en la dependencia no está clara. Como mencionó, si se promociona B.C al nivel superior C2, no hay muchas diferencias en cuanto al tipo de sistema, entonces ¿por qué A extends C2 está bien, pero no A extends B.C?Concedido un tipo anidado B.C tiene algún acceso privilegiado al contenido de B, pero no puedo encontrar nada en la especificación que haga que A extends B.C sea un problema.

El único problema es cuando C es una clase interna. Supongamos que B=A, A extends A.C deberían estar prohibidos, ya que existe una dependencia circular de "instancia adjunta". Esa es probablemente la verdadera motivación: prohibir que la clase exterior herede la clase interna. Las reglas reales son más generalizadas, porque son más simples y tienen sentido de todos modos, incluso para las clases no internas.

10

Imagine que usted es el compilador.

Te estamos diciendo que crees una clase Algo. Esta clase implementa Comportamiento ... Pero el Comportamiento aún no existe porque Algo no está registrado ...

¿Entiende el problema?

Ver clase como caja que contiene cosas. El comportamiento está contenido en la caja Algo. Pero algo no existe.

+3

Esta sería una respuesta válida si la pregunta era sobre C++. –

+1

Sí, pero el Comportamiento es una interfaz y, por lo tanto, no depende de la creación de Algo. –

+0

Sí, lo hace, porque esa interfaz es parte de Algo. Algo tiene que existir antes de que pueda referenciar Comportamiento, pero para crear Algo que necesite hacer referencia al Comportamiento. –

0

El simple hecho de que las especificaciones del lenguaje lo prohíben debería ser suficiente.

Algunas de las razones que se me ocurrieron:

  • No serían útiles.

  • Por cualquier razón que desee utilizar, estoy seguro de que existen mejores opciones.

  • Las clases secundarias deberían extender las clases base, entonces ¿por qué declararías una clase base dentro de su propio hijo?

  • Sería contra-intuitivo tener una clase separada para extender su clase interna.

+0

Sería útil para los casos que necesitamos que una interfaz de devolución de llamada pase a una clase diferente. – ismailarilik

Cuestiones relacionadas