2009-01-30 14 views
5

Tengo una pregunta sobre herencia y conversión en Java. Tengo las siguientes dos clases de ejemplo y una clase de prueba, y declaro mi pregunta después de las clases:Herencia y conversión en Java

public class Automobile { 
    public int var; 

    public Automobile() { 
     var = 1; 
    } 

    public String toString() { 
     return "AUTOMOBILE: " + var; 
    } 
} 


public class Porsche extends Automobile { 
    public int var; 

    public Porsche() { 
     var = 2; 
    } 

    public String toString() { 
     return "PORSCHE: " + var; 
    } 
} 

public class Test { 
    public static void main (String [] args) { 
     Porsche p = new Porsche(); 
     Automobile a = new Automobile(); 

     System.out.println ("(Automobile) p = " + (Automobile)p); 

     System.out.println ("(Automobile) p.var = " + ((Automobile)p).var); 
    } 
} 

La salida es:

(Automobile) p = PORSCHE: 2 
(Automobile) p.var = 1 

No entiendo por qué en la segunda sentencia que tengo 1. ¿No debería ser 2? Porque después yo echo p para automóvil en la primera declaración sigo teniendo PORSCHE: 2 como la representación de p - Entiendo que esto de la siguiente manera:

, sin embargo, he fundido p al automóvil p mantiene la "naturaleza original" - p es un objeto de la clase Porsche, pero como Porsche amplía Automobile, podríamos decir que p también es un automóvil. Y, por lo tanto, cuando lo lanzamos explícitamente a Automobile, continúa usando sus métodos: en nuestro caso es el método toString() definido en Porsche.

Por otro lado, si lo que escribo es correcta, entonces la segunda sentencia print debe dar 2 y no 1.

Ahora bien, esto parece como una contradicción a mí, pero ya que este funciona en Java, parece que no entiendo lo que sucede durante el casting y el proceso de herencia.

Respuesta

16

Creo que no puede anular las variables en Java. La subclase en realidad 'oculta' la variable var.

Cuando selecciones Automobile, obtendrá la versión de la clase superclass de la variable var. Sin embargo, el método toString() sigue buscando en la versión de la instancia de la variable var.

Si eliminó el public int var de la subclase Porsche, debería funcionar como se esperaba.

Debe tenerse en cuenta que no es una buena práctica usar variables de instancia públicas, siempre debe crear getters/setters para tener encapsulation correctamente.

5

Sombreado de la variable var.

Su Porche.var es una variable diferente de la Automobile.var.

Porsche.toString() El método utiliza la Porsche.var, mientras que el elenco le dice al compilador que utilice la versión Automobile.

2

El acceso a los campos no es polimórfico; depende únicamente del tipo de tiempo de compilación de la expresión.

La expresión ((Automóvil) p) tiene tiempo de compilación tipo Automóvil, por lo que se usan sus campos.

1

Al declarar la variable "var" en ambas clases, en realidad crea dos campos en la memoria.

Una instancia de "Porsche" tendrá dos campos "var" en la memoria, uno de la clase "Porsche" y uno de la superclase "Automóvil". El campo "var" de la superclase está oculto cuando se refiere a "var" de una instancia conocida de "Porsche".Si convierte esta instancia a "Automóvil" y hace referencia al campo "var", debe hacer referencia al campo var de "Automóvil".

No hay prioridad en los campos. Nuevos campos con el mismo nombre eclipsan los campos de la superclase.

Para obtener el resultado esperado, no debe declarar ningún campo "var" en la clase "Porsche".

0

Sin embargo:

Si usted tiene un método que devuelve una clase padre objeto, se puede devolver cualquier tipo de objeto de una clase que extiende (Ejemplo de fábrica). Ahora bien, si este método devuelve un objeto de clase B y si no lo convierte en B, todos sus atributos serán los atributos principales. Si lo haces en B, sus atributos serán A y B.

class A { 
int a1,a2; 
public A(){} 


    public static A getInstance() { 
    return new B() ; 
    } 
} 
class B { 
int b1,b2; 
    public B() {} 

} 
class Test{ 

public static void main (String [] args) { 

    A theA = A.getInstance() ; //here theA has only a1,a2 as attributes 
    B theB = (B)theA // here theB has b1,a2 and a1,a2 as attributes 
    } 


}