web-dev-qa-db-fra.com

Si vous écrasez un champ dans une sous-classe d'une classe, la sous-classe a deux champs avec le même nom (et un type différent)?

J'ai 3 classes:

public class Alpha {
    public Number number;
}

public class Beta extends Alpha {
    public String number;
}

public class Gama extends Beta {
    public int number;
}

Pourquoi le code suivant se compile-t-il? Et pourquoi le test réussit-il sans aucune erreur d'exécution?

@Test
public void test() {
    final Beta a = new Gama();
    a.number = "its a string";
    ((Alpha) a).number = 13;
    ((Gama) a).number = 42;

    assertEquals("its a string", a.number);
    assertEquals(13, ((Alpha) a).number);
    assertEquals(42, ((Gama) a).number);
}
49
fiction

Les variables membres ne peuvent pas être remplacées comme les méthodes. Les variables number dans vos classes Beta et Gama sont masquant (ne remplaçant pas) la variable membre number de la superclasse.

En castant, vous pouvez accéder au membre caché dans la superclasse.

67
Jesper

Les champs ne peuvent pas être remplacés; ils ne sont pas accessibles de manière polymorphe en premier lieu - vous déclarez simplement un nouveau champ dans chaque cas.

Il compile parce que dans chaque cas, le type de compilation de l'expression est suffisant pour déterminer quel champ appelé number vous voulez dire.

Dans la programmation du monde réel, vous éviteriez cela par deux moyens:

  • Bon sens: l'observation des champs rend votre code plus difficile à lire, alors ne le faites pas
  • Visibilité: si vous rendez tous vos champs privés, les sous-classes ne les connaîtront pas de toute façon
44
Jon Skeet