2011-05-03 7 views
14

¿El súper tiene mayor prioridad que la clase externa?exterior frente a la clase Súper

Considere tenemos tres clases:

  1. ClassA
  2. ClassB
  3. clase Anonymous en ClassB que se extiende claseA

ClassA.java:

public class ClassA { 
    protected String var = "A Var"; 

    public void foo() { 
     System.out.println("A foo()"); 
    } 
} 

ClassB. java:

public class ClassB { 
    private String var = "B Var"; 

    public void test() { 

     new ClassA() { 
      public void test() { 
       foo(); 
       System.out.println(var); 
      } 
     }.test(); 
    } 

    public void foo() { 
     System.out.println("B foo()"); 
    } 
} 

Cuando llamo new ClassB().test(), me sale el siguiente resultado (que es más o menos lo esperado):

A foo() 
A Var 

Pregunta: ¿Se ha definido en alguna parte que la clase interna toma (métodos y miembros) en primer lugar de la superclase y después de la clase externa o es JVM aplicación compilador dependiente? He revisado el JLS (§15.12.3) pero no encontré ninguna referencia para eso, tal vez se indique allí pero no entendí algunos de los términos.

+3

Traté de seguir la lógica en el JLS pero aún no tenía mi café ;-) Por experiencia, yo diría: estoy ** bastante ** seguro de que esto está bien especificado y ** no * * Depende de la implementación. Y * si * dependía de la implementación, dependería del compilador y no de la JVM, ya que esa decisión se toma en tiempo de compilación. –

+0

@Joachim - Escribí JVM por error, gracias por señalarlo. – MByD

Respuesta

5

Ver 6.3.1 Shadowing Declarations:

Una declaración d de un método denominado nsombras las declaraciones de cualesquiera otros métodos denominados n que están en un ámbito circundante en el punto donde d ocurre en todo el alcance de d.

Qué puede interpretarse como "la declaración de foo (heredado de ClassA) las sombras de la declaración de cualesquiera otros métodos denominados foo que se encuentran en un ámbito circundante (ClassB) en el punto donde se produce foo, durante todo el alcance de foo. "

También relevante - sección 15.12.1:

15.12.1 de tiempo de compilación Paso 1: Determinar la Clase o Interfaz a Buscar

El primer paso en el procesamiento de una invocación de método en tiempo de compilación es averigüe el nombre del método que se invocará y qué clase o interfaz comprobará las definiciones de los métodos de ese nombre.Hay varios casos a considerar, dependiendo de la forma que precede al paréntesis izquierdo, de la siguiente manera:

  • Si la forma es MethodName, entonces hay tres sub-casos:
    • Si se trata de un simple nombre, es decir, solo un Identificador, entonces el nombre del método es el Identificador. Si el identificador aparece dentro del alcance (§6.3) de una declaración de método visible con ese nombre, entonces debe haber una declaración de tipo adjunta de la cual ese método es miembro. Deje que T sea la declaración de tipo más interna. La clase o interfaz para buscar es T.
    • Si es un nombre calificado de la forma TypeName.Identifier, [...]
    • En todos los demás casos, el nombre calificado tiene el formato FieldName.Identifier; a continuación, [...]
+0

@aioobe - Gracias, pero todavía no está claro para mí, porque los métodos y miembros de ClassB están en el ámbito de la clase anónima. Puede que me esté perdiendo eso, pero aún no veo prioridad para la súper clase (Clase A en mi ejemplo) en lo que publicaste. – MByD

+0

Hmm ... cierto. Veré si puedo encontrar algo más específico. – aioobe

+0

@aioobe - gracias de nuevo, espero que no piense que le estoy enviando a que el trabajo para mí, Yo miraba una y otra vez y no podía entenderlo ... – MByD

1

Creo que siempre va a obtener "A var".

Esto se debe a que su implementación de método test() se está definiendo en una subclase anónima de A. No creo que pueda acceder a la variable de instancia B.var en su método test() a menos que se refiera explícitamente a la clase externa usando ClassB.this.var.

+0

@The Captain: si elimino 'var' de ClassA, obtengo la var de ClassB. Intento entender y obtener confirmación sobre lo que debería suceder en caso de que no lo elimine. – MByD

+0

seguro ... Creo que esto es porque 'ClassA''var' está sombreando' ClassB' .var' en tu ejemplo. Entonces, aunque ambas definiciones existen, al hacer referencia a 'var' desde' A.test() 'siempre se obtendrá la versión' ClassA'. –

Cuestiones relacionadas