71 votes

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 compile-t-il ? Et, pourquoi le test passe-t-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);
}

91voto

Jesper Points 65733

Les variables membres ne peuvent pas être surchargées comme les méthodes. Le site number variables dans vos classes Beta y Gama sont cacher (sans remplacer) la variable membre number de la superclasse.

Par casting, vous pouvez accéder au membre caché dans la superclasse.

56voto

Jon Skeet Points 692016

Les champs ne peuvent pas être Remplacé par ; 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 l'expression au moment de la compilation est suffisant pour déterminer dont champ appelé number vous voulez dire.

Dans le monde réel de la programmation, vous éviterez cela de deux manières :

  • Le bon sens : l'ombrage 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.

3voto

yoAlex5 Points 2350

Lorsque le successeur a un champ avec le même nom comme champ d'une superclasse, il est appelé - Masquer un champ

Le champ Java ne supporte pas le polymorphisme et ne prend pas en compte le type d'un champ.

class A {
    String field = "A: field";

    String foo() {
        return "A: foo()";
    }
}

class B extends A {
    //B's field hides A's field
    String field = "B: field";

    String foo() {
        return "B: foo()";
    }
}

@Test
public void testPoly() {
    A a = new A();
    assertEquals("A: field", a.field);
    assertEquals("A: foo()", a.foo());

    B b = new B();
    assertEquals("B: field", b.field);
    assertEquals("B: foo()", b.foo());

    //B cast to A
    assertEquals("A: field", ((A)b).field);  //<--
    assertEquals("B: foo()", ((A)b).foo());
}

[Propriété prioritaire de Swift]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X