¿Puede Java llamar al método reemplazado por los padres en otros objetos pero no subtipo?

aquí está trabajando código Java

class Cup { public String sayColor() { return "i have a color ."; } } class TCup extends Cup{ public String sayColor(){ System.out.println(super.getClass().getName()); return super.sayColor()+"color is tee green."; } } class MyTCup extends TCup { public String sayColor(){ System.out.println(super.getClass().getName()); return super.sayColor()+"but brushed to red now!"; } } class Test { public static void main(String[] args) { Cup c = new MyTCup(); System.out.print(c.sayColor()); } } 

y ejecutando las impresiones de la clase de prueba

 MyTCup MyTCup i have a color .color is tee green.but brushed to red now! 

pregunta 1: En el tiempo de ejecución, el tipo del objeto C es MyTCup, pero siempre puede llamar al método súper. ¿Hay una stack de métodos en la memoria dentro de MyTCup después de inicializar el objeto, y luego puede llamar en tiempo de ejecución como el código?

pregunta 2: No hay forma de llamar al supermétodo en otros objetos. Como sé, c ++ puede convertir el método padre en cualquier momento. ¿Por qué diseño java como este?

No se puede llamar al supermétodo en otros objetos, eso violaría la encapsulación. El punto es que el objeto controla lo que hacen sus métodos reemplazados. Por ejemplo, puede anular el método de add una colección para lanzar una excepción en ciertas circunstancias, por lo que podría garantizar que solo se agreguen elementos “válidos” a la colección. ¡Eso no tendría sentido si los llamadores pudieran evitarlo con un yeso!

La única razón por la que un objeto puede llamar a super.foo() por sí mismo es permitir que se implemente una llamada mediante la implementación principal. Depende del código de la clase asegurarse de que solo lo haga con sensatez. Una vez más, para tomar el ejemplo de agregar una colección, si la colección reemplaza add que debería tener alguna forma de agregar el elemento validado a la colección, lo que haría con super.add() .

Tenga en cuenta que por la misma razón de la encapsulación, solo puede llamar a la implementación principal, no a la implementación de abuelos, por lo que super.foo() es válido, pero super.super.foo() no lo es.

1:

Tu pregunta no está del todo clara. ¿A qué te refieres con “llamar en tiempo de ejecución como el código”? Si se pregunta cómo la instancia c sabe cuál es su superclase, entonces sí, la jerarquía de clases se almacena en la memoria y la VM puede acceder a ella.

2:

Java realmente le permite lanzar una instancia a su padre. Es solo que llamar a un método en una instancia siempre usa la clase real de la instancia, no su clase en tiempo de comstackción. Es decir, en Java todos los métodos son lo que se llamaría “virtual” en C ++. Por qué esto fue decidido, no lo sé.

Editar: en realidad, Jon Skeet explica muy bien por qué no se puede llamar a un método de una superclase en una instancia de una subclase, por lo que ahora sé :-).

Puede definir un nuevo método de ayuda en la subclase para que no anule el original – invoque eso – puede llamar al súper método o no, dependiendo de lo que desee.

En realidad puedes, pero debes usar una metodología, por lo que solo funcionará en tu código.
En la superclase, agrega el parámetro “Clase” al método, como en:

 public String sayColor(Class classFilter){... 

ahora, en cada anulación, comprueba si la subclase actual es la del filtro especificado como:

 if(TCup.class!=classFilter)return super.sayColor(classFilter); return "some text for TCup only"; 

Codifiqué de forma exclusiva. Puede agregar más parámetros, o comparar con nulo, para que pueda unir los resultados con las súper clases, use su creatividad 🙂