Если вы перезаписываете поле в подклассе класса, в подклассе есть два поля с одинаковым именем (и разным типом)?

У меня есть 3 класса:

public class Alpha {
    public Number number;
}

public class Beta extends Alpha {
    public String number;
}

public class Gama extends Beta {
    public int number;
}

Почему следующий код компилируется? И почему тест проходит без ошибок во время выполнения?

@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);
}

person fiction    schedule 23.02.2012    source источник
comment
И? это так работает. Если вам нужно переопределить, вы должны использовать методы setter/getter. Публичное поле — почти всегда плохая идея.   -  person kan    schedule 23.02.2012


Ответы (3)


Переменные-члены не могут быть переопределены, как методы. Переменные number в ваших классах Beta и Gama скрывают (не переопределяют) переменную-член number суперкласса.

Путем приведения вы можете получить доступ к скрытому члену в суперклассе.

person Jesper    schedule 23.02.2012
comment
См. в учебниках по Java™ Скрытие полей - person bigspawn; 11.05.2018

Поля нельзя переопределить; во-первых, к ним нет полиморфного доступа - вы просто объявляете новое поле в каждом случае.

Он компилируется, потому что в каждом случае типа выражения времени компиляции достаточно, чтобы определить, какое поле с именем number вы имеете в виду.

В реальном программировании этого можно избежать двумя способами:

  • Здравый смысл: затенение полей затрудняет чтение кода, так что просто не делайте этого
  • Видимость: если вы сделаете все свои поля приватными, подклассы все равно не узнают о них
person Jon Skeet    schedule 23.02.2012

Когда у преемника есть поле с тем же именем, что и у поля суперкласса, это называется - Скрытие поля

Поле Java не поддерживает полиморфизм и не учитывает тип поля.

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());
}

[свойство переопределения Swift]

person yoAlex5    schedule 01.06.2020