2010-02-10 6 views
4

DONNÉ:héritage et membres classe

class A 
{ 
    String s = "A"; 
} 

class B extends A 
{ 
    String s = "B"; 
} 

public class C 
{ 
    public static void main(String[] args){ new C().go();} 
    void go() 
    { 
     A a = new B(); 
     System.out.println(a.s); 
    } 
} 

Question:

Quels sont les mécanismes derrière JVM lorsque ce code est exécuté? Comment se fait-il que a.s s'imprime en "A".

+0

En plus des autres réponses, notez qu'il n'y a pas d'accès au membre s de B en utilisant un sans le rétrograder à B, par ex. ((B) a) .s –

Répondre

4

références sur le terrain ne sont pas soumis à un polymorphisme, donc au moment de la compilation le compilateur fait référence le champ A parce que votre variable locale est de type A.

En d'autres termes, le comportement sur le terrain est comme le comportement de surcharge Java sur les méthodes , pas le comportement de substitution de Java.

+0

Merci pour votre réponse. Si vous me permettez de clarifier votre réponse, voici ce qui suit: [1] Y a-t-il une différence entre ce que «a» contient à l'exécution et à la compilation? [2] A quel moment du code se trouve le mécanisme de surcharge? – Krolique

+0

err, correction: [2] .... est-ce que le mécanisme actuel de "surcharge" se produit? =) – Krolique

+0

@Krolique, A ne contient réellement rien au moment de la compilation (c'est juste une définition, ce n'est pas un code exécuté). La surcharge se produit lorsque vous définissez une variable s dans la classe B. À ce stade, vous avez deux champs avec le même nom dans deux classes différentes. Le compilateur est celui qui détermine lequel vous voulez référencer dans votre code. Ce n'est pas dynamique. – Yishai

1

Ce n'est pas un polymorphisme (comme marqué).

Java a virtual methods, et non variables de membre virtuel - c'est-à-dire que vous ne remplacez pas une propriété - vous la cachez.

+1

Ce n'est pas une propriété, c'est un champ. –

+0

et une variable membre. la terminologie n'est pas stricte – Bozho

+0

Merci pour votre réponse. J'ai manqué la différence subtile entre les méthodes virtuelles (héritées?) Et le membre. – Krolique

2

Vous vous attendez probablement à ce que des champs soient remplacés comme une méthode, avec une répartition dynamique basée sur le type d'exécution de l'objet.

Ce n'est pas comme cela que fonctionne Java. Les champs ne sont pas écrasés, ils sont cachés. Cela signifie qu'un objet de la classe B a deux champs nommés "s", mais lequel d'entre eux est accessible dépend du contexte. Pour ce qui est de la raison: il ne serait pas vraiment utile de surcharger les champs, car il n'y a aucun moyen utile de le faire fonctionner quand les types sont différents, et simplement aucun point quand le type est le même (comme vous pouvez simplement utiliser le champ superclasse). Personnellement, je pense que ce devrait simplement être une erreur de compilateur.

+0

Merci pour votre réponse. Juste voir si j'ai saisi le concept correctement. Le contexte implique un type déclaré? Disons s'il était possible de monter et j'ai fait ce qui suit: B b = new A(); alors en b.s devrait imprimer "B"? – Krolique

+0

Puisque ce n'est pas possible, il est inutile de dire ce qu'il devrait "imprimer", mais oui, c'est l'idée de base. –

+0

Merci, je pense que cela clarifie beaucoup les choses! – Krolique

0

Bien que les variables membres soient héritées d'une classe de base, elles ne sont pas appelées de façon polymorphe (l'appel dynamique ne s'applique pas aux variables membres). Ainsi, a.s se référera au membre de la classe de base et non à la classe dérivée. Cela dit, le code ne suit pas les principes OO. Les membres d'une classe doivent être privés/protégés (non public ou par défaut) en fonction du cas d'utilisation de l'entreprise et vous devez fournir des méthodes publiques pour obtenir et définir les valeurs du membre.

+0

Merci de votre réponse. Dans toutes les circonstances normales, je ferais comme vous l'avez suggéré. – Krolique