class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
}
public void doIt()
{
new Son().printMe();
}
La función imprimirá "papá". ¿Hay alguna manera de hacer que imprima "hijo"?
java
inheritance
overriding
Dikla
fuente
fuente
Respuestas:
Si. Pero en lo que respecta a la variable, se sobrescribe (dar un nuevo valor a la variable. Dar una nueva definición a la función es anular).
Just don't declare the variable but initialize (change) in the constructor or static block.
El valor se reflejará cuando se use en los bloques de la clase padre
si la variable es estática, cambie el valor durante la inicialización con el bloque estático,
o bien cambio en el constructor.
También puede cambiar el valor más adelante en cualquier bloque. Se reflejará en super clase
fuente
class Son extends Dad { static { me = 'son' } }
En resumen, no, no hay forma de anular una variable de clase.
No anula las variables de clase en Java, las oculta. La anulación es, por ejemplo, los métodos. Ocultar es diferente de anular.
En el ejemplo que ha dado, al declarar la variable de clase con el nombre 'yo' en la clase Hijo, oculta la variable de clase que habría heredado de su superclase Dad con el mismo nombre 'yo'. Ocultar una variable de esta manera no afecta el valor de la variable de clase 'yo' en la superclase Dad.
Para la segunda parte de su pregunta, sobre cómo hacer que se imprima "hijo", establecería el valor a través del constructor. Aunque el código a continuación se aparta bastante de su pregunta original, yo escribiría algo como esto;
El JLS da muchos más detalles sobre cómo esconderse en la sección 8.3 - Declaraciones de campo
fuente
Person
supone que debe reemplazar en este ejemplo?Son
yDad
se supone que heredan dePerson
, luego llamansuper("Son or Dad");
a sus constructores.Sí, simplemente anule el
printMe()
método:fuente
printMe()
método, o incluso si tiene ese método, es un método estático?Puede crear un captador y luego anularlo. Es particularmente útil si la variable que está anulando es una subclase de sí misma. Imagine que su superclase tiene un
Object
miembro pero en su subclase ahora está más definido para ser unInteger
.fuente
Si lo va a anular, no veo una razón válida para mantener esto estático. Sugeriría el uso de la abstracción (ver código de ejemplo). :
Ahora podemos agregar al papá:
el hijo:
y papá conoció a una buena dama:
Parece que tenemos una familia, digamos al mundo sus nombres:
}
Salida System.out: Tommy Nancy Dad
System.err es el mismo que el anterior (solo tiene una fuente roja)
Salida JOption:
Tommy luego
Nancy y luego
Dad
fuente
Esto parece un defecto de diseño.
Elimine la palabra clave estática y establezca la variable, por ejemplo, en el constructor. De esta manera, Son simplemente establece la variable en un valor diferente en su constructor.
fuente
Aunque es cierto que las variables de clase solo pueden ocultarse en subclases y no anularse, aún es posible hacer lo que quiera sin anular
printMe ()
en subclases, y la reflexión es su amiga. En el siguiente código, omito el manejo de excepciones para mayor claridad. Tenga en cuenta que declararme
comoprotected
no parece tener mucho sentido en este contexto, ya que estará oculto en las subclases ...fuente
... imprimirá "hijo".
fuente
https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html
Se llama Ocultar campos
Desde el enlace de arriba
fuente
solo anulando
printMe()
:la referencia a
me
en elDad.printMe
método apunta implícitamente al campo estáticoDad.me
, por lo que de una forma u otra está cambiando lo queprintMe
hace enSon
...fuente
No puede anular variables en una clase. Puede anular solo los métodos. Debe mantener las variables privadas, de lo contrario puede tener muchos problemas.
fuente
De hecho, imprime 'papá', ya que el campo no se anula sino que se oculta. Hay tres enfoques para hacerlo imprimir 'hijo':
Enfoque 1: anular printMe
Enfoque 2: no oculte el campo e inicialícelo en el constructor
Enfoque 3: use el valor estático para inicializar un campo en el constructor
fuente
Las variables no participan en la sobreescritura. Solo los métodos lo hacen. Una llamada a un método se resuelve en tiempo de ejecución, es decir, la decisión de llamar a un método se toma en tiempo de ejecución, pero las variables se deciden solo en tiempo de compilación. Por lo tanto, se llama a esa variable cuya referencia se usa para llamar y no al objeto de tiempo de ejecución.
Eche un vistazo al siguiente fragmento:
Cuando ejecute el código, la consola mostrará:
fuente
Por supuesto, usar atributos privados y getters y setters sería lo recomendado, pero probé lo siguiente y funciona ... Ver el comentario en el código
Entonces ... ¿acabo de redefinir las reglas de herencia o puse a Oracle en una situación difícil? Para mí, la cadena estática protegida me está claramente anulada, como puede ver cuando ejecuta este programa. Además, no tiene ningún sentido para mí por qué los atributos no deberían ser reemplazables.
fuente
¿Por qué desearía anular variables cuando podría reasignarlas fácilmente en las subclases?
Sigo este patrón para evitar el diseño del lenguaje. Suponga un caso en el que tiene una clase de servicio importante en su marco que debe usarse en diferentes tipos en múltiples aplicaciones derivadas. En ese caso, la mejor manera de configurar la lógica de superclase es reasignando sus variables 'definitorias'.
fuente
No. Las variables de clase (también aplicables a las variables de instancia) no exhiben una función de anulación en Java ya que las variables de clase se invocan en función del tipo de objeto de llamada. Se agregó una clase más (Humano) en la jerarquía para que quede más claro. Entonces ahora tenemos
Hijo extiende papá extiende humano
En el siguiente código, intentamos iterar sobre una matriz de objetos Humanos, Papá e Hijo, pero imprime los valores de la Clase Humana en todos los casos, ya que el tipo de objeto de llamada era Humano.
Imprimirá
Si deseamos acceder a la variable de clase del objeto real desde una variable de referencia de su clase primaria, debemos decirle explícitamente esto al compilador mediante la conversión de la referencia primaria (objeto humano) a su tipo.
Imprimirá
Sobre cómo parte de esta pregunta: - Como ya se sugirió, anule el método printMe () en la clase Son, luego al llamar
La variable "yo" de la clase de papá se ocultará porque la declaración más cercana (del método printme () de la clase Son) del "yo" (en la clase Son) tendrá prioridad.
fuente
Simplemente llame a super.variable en el constructor de subclase
La salida es 10.
fuente