una tipos otra objeto genericas externas ejemplo dentro crear clases clase anonimas anonima anidadas java methods java-8 anonymous-class method-reference

java - tipos - Método de acceso de la clase anónima externa desde la clase anónima interna



meter una clase dentro de otra java (3)

Desde Java 8 la solución es bastante fácil. Solo guarda la referencia del método en una variable.

ReturnsANumber v = new ReturnsANumber() { int theNumber() { return 119; } public int getIt() { Supplier<Integer> supplier = this::theNumber; ReturnsANumber w = new ReturnsANumber() { int theNumber() { return 1; } public int getIt() { return supplier.get(); } }; return w.getIt(); } };

Almacenar el objeto exterior también podría hacer el truco. Pero solo para métodos heredados :

interface ReturnsANumber { int theNumber(); int getIt(); } public int getIt() { ReturnsANumber outer = this; ReturnsANumber w = new ReturnsANumber() { public int theNumber() { return 1; } public int getIt() { return outer.theNumber(); } }; return w.getIt(); }

También puede almacenar la referencia del método o el objeto externo como un campo.

Actualizar

@Holger propuso otra solución. Puedes pasar tu objeto exterior a un lambda:

ReturnsANumber v = new ReturnsANumber() { ... @Override public int getIt() { ReturnsANumber w = Optional.of(this).map(outer -> new ReturnsANumber() { int theNumber() { return 1; } public int getIt() { return outer.theNumber(); } }).get(); return w.getIt(); } };

Hago una instancia de una clase anónima con un método que crea una instancia de otra clase anónima, y ​​desde esta clase anónima interna quiero llamar a un método que pertenece a la clase anónima externa. Para ilustrarlo, supongamos que tengo esta interfaz:

interface ReturnsANumber { int getIt(); }

Y luego, en algún lugar de mi código, hago esto:

ReturnsANumber v = new ReturnsANumber() { int theNumber() { return 119; } public int getIt() { // In a modern version of Java, maybe I could do // var a = this; // and then call a.theNumber(); ReturnsANumber w = new ReturnsANumber() { int theNumber() { return 1; } public int getIt() { return this.theNumber(); } }; return w.getIt(); } }; System.out.println("The number is " + v.getIt());

Pregunta: En el método más interno getIt , quiero llamar a theNumber() pertenece a la clase anónima más externa. ¿Cómo puedo lograr eso sin usar la función Java 10 var (como se indica en el código)?

Aclaración: Idealmente, la clase anónima externa no debería necesitar saber que la clase interna desea llamar a su método theNumber . La idea es crear un código que permita que la clase interna llame sin ambigüedad a cualquier método en la clase externa.

En otras palabras, ¿cómo puedo hacer que este código aparezca: The number is 119 (en lugar de mostrar The number is 1 )

Motivación : alguien podría preguntarme por qué quiero hacer esto de todos modos: estoy escribiendo algún tipo de generador de código y quiero estar seguro de que el código que estoy generando no es ambiguo.


No hay ninguna palabra clave para acceder a la clase anónima adjunta.

Pero una solución podría ser enviar un proxy al método en la clase anónima externa y hacer una referencia no calificada:

ReturnsANumber v = new ReturnsANumber() { int theNumber() { return 119; } //Just a different name for theNumber() int theNumberProxy() { return theNumber(); } public int getIt() { ReturnsANumber w = new ReturnsANumber() { int theNumber() { return 1; } public int getIt() { return theNumberProxy(); //calls enclosing class''s method } }; return w.getIt(); } };

La necesidad de tal maniobra debe ser prueba suficiente de que la estructura de su clase no es ideal y podría ser una trampa de mantenimiento. Simplemente podría reemplazar la primera clase anónima con una clase estática anidada, por ejemplo.


Si puedes extender la interfaz:

public class Test { interface ReturnsANumber { int theNumber(); int getIt(); } public static void main(String[] args) { ReturnsANumber v = new ReturnsANumber() { public int theNumber() { return 119; } public int getIt() { final ReturnsANumber that = this; // In a modern version of Java, maybe I could do // var a = this; // and then call a.theNumber(); ReturnsANumber w = new ReturnsANumber() { public int theNumber() { return 1; } public int getIt() { return that.theNumber(); } }; return w.getIt(); } }; System.out.println("The number is " + v.getIt()); } }