Вопрос-ответ

If you overwrite a field in a subclass of a class, the subclass has two fields with the same name(and different type)?

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

У меня есть 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);
}
Переведено автоматически
Ответ 1

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

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

Ответ 2

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

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

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


  • Здравый смысл: затенение полей затрудняет чтение вашего кода, поэтому просто не делайте этого

  • Видимость: если вы сделаете все свои поля закрытыми, подклассы все равно не будут знать о них

Ответ 3

Java Скрывает поле

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

Поле 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]

Ответ 4

В качестве обходного пути вы можете использовать методы получения:

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

String getField() {
return field;
}
}

class B extends A {
private String field = "B: field";

@Override
String getField() {
return field;
}
}
java