¿Puede Java llamar al método anulado padre en otros objetos pero no en un subtipo?

StackOverflow https://stackoverflow.com/questions/1032847

  •  06-07-2019
  •  | 
  •  

Pregunta

aquí está funcionando el código de 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 ejecutar la clase de prueba imprime

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 de objeto C es MyTCup, pero siempre puede llamar al método super. ¿Hay una pila 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 método super en otros objetos. Como sé, c ++ puede emitir para llamar al método padre en cualquier momento. ¿Por qué es diferente en Java?

¿Fue útil?

Solución

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 anulados. Por ejemplo, puede anular el método add de una colección para lanzar una excepción en ciertas circunstancias, por lo que podría garantizar que solo " válido " Se agregaron elementos a la colección. ¡Eso no tendría sentido si las personas que llaman pudieran evitarlo con un yeso!

La única razón por la que un objeto llama a super.foo () por sí mismo es para permitir que se implemente una llamada utilizando la implementación principal. Depende del código en la clase asegurarse de que solo lo haga con sensatez. Nuevamente, para tomar el ejemplo de agregar una colección, si la colección anula add , tendría que tener alguna forma de agregar el elemento validado a la colección, que funcionaría con super.add () .

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

Otros consejos

1:

Su pregunta no está del todo clara. ¿Qué quiere decir 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 compilación. Es decir. en Java todos los métodos son lo que se llamaría "virtual" en C ++. Por qué se decidió esto, 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, así que ahora sé :-).

Puede definir un nuevo método auxiliar en la subclase para que no sobrescriba el original, llame a eso, puede llamar al método super o no, dependiendo de lo que desee.

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

public String sayColor(Class classFilter){...

ahora, en cada anulación, verifica 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 manera exclusiva. Puede agregar más parámetros o comparar con nulo, para que pueda unir resultados con las superclases, use su creatividad :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top