2011-08-02 17 views
14

Mientras exploraba las preguntas scjp, me encontré con este comportamiento que me pareció extraño.Problema de herencia de Java

me han declarado dos clases artículo y el perno de la siguiente manera:

class Item { 
    int cost = 20; 

    public int getCost() { 
     return cost; 
    } 
} 

class Bolt extends Item { 
    int cost = 10; 

    public int getCost() { 
     return cost; 
    } 
} 

y trató de acceder al valor de costo el doble

public class Test { 
    public static void main(String[] args) { 
     Item obj = new Bolt(); 
     System.out.println(obj.cost); 
     System.out.println(obj.getCost()); 
    } 
} 

La salida que se ve es 20 10. lo que pueda' Entiendo cómo sucede esto.

+0

No. @Override es solo una indicación para el compilador de que desea que este método anule a otro, y que debería producir un error si no es el caso. Pero tan pronto como los métodos tengan la misma firma, el segundo reemplaza al primero. Las anotaciones no existían antes de Java 5. –

+0

@netbrain, el método getCost de la subclase funciona bien. Tenía curiosidad sobre el resultado de llamar directamente a obj.cost. Pero como Sanjay dice, se debe al hecho de que el polimorfismo en tiempo de ejecución es aplicable solo a los métodos, no a los campos. –

Respuesta

19

obj es una referencia de tipo Item por lo tanto la primera 20 ya que el valor de cost campo de Item es 20. El segundo valor es 10 porque el tipo de tiempo de ejecución de obj es Bolt y por lo tanto getCost() invoca getCost de Bolt clase (desde Bolt extiende Item).

En resumen, el polimorfismo de tiempo de ejecución solo se aplica a los miembros de la instancia (anulación de método) y no a los campos de instancia.

+1

sí. y una razón más para evitar los campos públicos. –

+0

Entonces, ¿hay dos campos de costos en un objeto Bolt? – bcr

+0

Desde una perspectiva de detalle de implementación, solo se crea * un * objeto cuando dices 'nuevo Bolt()'. Pero sí, la subclase es bastante consciente de los campos/métodos de sus hosts de superclase. Puede verificar esto agregando un tercer 'sysout' en su código:' System.out.println (((Bolt) obj) .cost) ' –

7

Los campos de clase no participan en el juego de polimorfismo. Los métodos lo hacen.

Por lo tanto, cuando acceda al campo, vaya a uno que esté definido en la clase base porque el tipo de objeto es Item. Cuando llamas al método, obtienes el valor real porque invocas un método que usa polimorfismo.

Conclusión:

Los campos son siempre privados. Si desea acceder al método de escritura de campo.

+0

Esto, y la respuesta de Sanjay lo dejó claro para mí. –