2009-10-19 23 views
7

Estoy confundido por qué esto está permitidoLa subclasificación clase interna de la clase externa versus otra clase interna

public class Foo { 
    class Bar extends Foo { 
    } 
} 

Sin embargo, esto no está permitido

public class Foo { 
    class Bar extends Foo { 
    } 

    class Fooey extends Bar { 
    } 
} 

El compilador informó de que no puede hacer referencia a Fooey.this antes de que se haya llamado al constructor de supertipo.

Y esto está permitido

public class Foo { 
    static class Bar extends Foo { 
    } 

    class Fooey extends Bar { 
    } 
} 

¿Qué está pasando aquí? ¿Y a dónde puedo ir para obtener más información sobre cómo funciona la herencia de la clase interna?

EDIT Me encontré con ideas bastante pobres; la clase interna se extiende a la clase externa y la clase interna se extiende a otra clase interna estática. No estaba seguro de qué iba exactamente y cómo debería refactorizar esto. Terminé tirando de las clases internas y encapsulándolas en la clase externa.

+0

Echa un vistazo a esta pregunta, bastante seguro de que esto lo duplica: http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class –

+0

No es una tontería (al menos no de esa) –

+0

¿De qué sirve tener una instancia externa de una clase que estás ampliando? – Jorn

Respuesta

6

En primer lugar: No hacer este tipo de cosas. Es malvado En realidad, Java 1.1 debería haberse especificado mucho más restrictivamente, IMO.

Existe una confusión acerca de qué this utilizar desde el constructor Foo.Fooey. El exterior esto (Foo.this) funcionaría. Pero el this real es un Foo pero no se puede pasar al superconstructor debido a las reglas sobre el uso de this antes de que el superconstructor regrese (y además de tener una instancia externa, la misma instancia que la instancia interna está cargada). El exterior esta en la superclase "((Bar)this).this$0" (IIRC), también es inaccesible debido a restricciones de uso de this.

La solución es ser explícito. Explícito suele ser algo bueno en mi libro (a menos que se convierta en repetitivo).

public class Foo { 
    class Bar extends Foo { 

    } 

    class Fooey extends Bar { 
     Fooey() { 
      Foo.this.super(); 
     } 
    } 
} 

Mejor aún, no tiene una clase interna que extienda su propia clase externa, o extienda cualquier clase interna.

+0

+1 para su primera observación. Si tiene que crear explícitamente un constructor, porque el predeterminado no se compila, diría que lo está haciendo mal (en lo que respecta al diseño). – Jorn

+0

Tom, gracias por la respuesta. Me encontré con ideas bastante pobres; la clase interna se extiende a la clase externa y la clase interna se extiende a otra clase interna estática. No estaba seguro de lo que estaba pasando. – sal

1

Tom Hawtin La respuesta es correcta.

También eche un vistazo a java puzzler. El capítulo de muestra contiene este caso y algunos otros casos "interesantes" que tal vez quiera consultar.

1

(no puedo hacer ningún comentario todavía - Necesito 50 rep)

También estoy aturdida que esto está permitido. Una clase interna (no estática) de una clase externa es en realidad un miembro de esa clase externa. Leer: un objeto interno es un miembro de su objeto externo. (Por cierto, cada objeto externo debe tener un objeto interno pero esto es además del punto.)

La analogía que me gusta usar es esta: deje que Car sea la clase externa y deje que Wheel sea la clase interna. Cada instancia de Car debe tener, y lo tiene, al menos una instancia de Wheel como miembro.

Ahora no tiene sentido conceptual para una clase interna para extender una clase exterior. No puedo pensar en ninguna situación del mundo real que requiera que un objeto sea tanto un miembro como un tipo de otro objeto. Set Theorists recordará el Axiom of Regularity y sus consecuencias.

creo que de esta manera: Que Honda extienden Car, y vamos Honda ser una clase interna anidado dentro Car. Lo que está diciendo aquí es que cada objeto Hondaes unaCar objeto (duh), y cada objeto Cartiene un objetoHonda. Solo una de estas afirmaciones tiene sentido, pero se permite que ambas sean verdaderas en Java.

o de nuevo a la analogía anterior, no debe dejar que se extienden WheelCar porque entonces habría un Wheelser un Car, y por definición debe tener otra Wheel, que por cierto es una Car y por lo tanto, debe tener tenerWheel y siempre Amén. La construcción de un objeto Car daría como resultado un bucle infinito de objetos anidados.

Estoy molesto porque esto es legal y no produce un error en tiempo de compilación.

+0

¡Imagine qué tan molesto estaría si lo viese en el código de producción! – sal

+0

Si Honda extiende el automóvil, * no * significa que cada objeto del automóvil tiene un objeto Honda. – RAY

+0

@RAY: sí, pero si Honda está anidado dentro de Car (es decir, un "miembro" de Car), significa * que * cada objeto de Auto tiene un objeto Honda. – chharvey

Cuestiones relacionadas