Учитывая класс "Bar", который расширяет класс "Foo", который реализует интерфейс "DeeDum"
public interface DeeDum {
public String getDee();
public String getDum();
}
public class Foo implements DeeDum {
public String dee = "D";
public String dum;
public String getDee() { return dee; }
public String getDum() { return dum; }
}
public class Bar extends Foo {
public String dee = "DEE";
public String dum = "DUM";
}
Почему это не работает?
public static Bar mybar = new Bar();
Assert.assertEquals("DEE", mybar.getDee());
Assert.assertEquals("DUM", mybar.getDum());
Вместо этого я получаю "D" и ноль. Другими словами, Bar не наследует методы доступа от Foo и не может переопределять свойства. Каким-то образом вызов mybar.getDum () вызывает статический экземпляр класса Foo и возвращает статические свойства из родительского класса. Даже если свойства переопределены в дочернем классе! Означает ли это, что вы не можете наследовать любые методы или свойства?
Я не могу обернуть голову вокруг этого. Почему Java не может наследовать средства доступа (и почему они выбрали такую странную альтернативу?)
Или я просто что-то не так делаю?
На самом деле, я вижу что-то странное и недетерминированное. Если у вас есть другой класс Bar, который расширяет Foo и устанавливает унаследованные методы доступа в блоке инициализации
Хотя вы можете установить родительское свойство в вышеприведенном блоке, оно фактически не создает копию для дочернего класса.
Кажется, это недетерминированная инициализация для нескольких классов.
Так что, если у вас есть Bar и Baz, которые оба расширяют foo и имеют блок инициализации, кажется, что оба наследуют значение, установленное Bar.
public class Bar extends Foo {
{
dee = "dee";
dum = "dum";
}
}
public class Baz extends Foo {
{
dee = "DEE";
dum = "DUM";
}
}
public static Bar bar = new Bar();
public static Baz baz = new Baz();
System.out.println("mybaz: " + mybaz.getDee() + mybaz.getDum()); // DEEDUM
System.out.println("mybar: " + mybar.getDee() + mybar.getDum()); // DEEDUM
но если они создаются в другом порядке, я получаю:
public static Baz baz = new Baz();
public static Bar bar = new Bar();
System.out.println("mybaz: " + mybaz.getDee() + mybaz.getDum()); // deedum
System.out.println("mybar: " + mybar.getDee() + mybar.getDum()); // deedum
И все же все по-другому, если в базовом классе Foo установлено значение по умолчанию.
Мне кажется, теперь я понимаю, что блок инициализации в Bar и Baz фактически устанавливает Foo :: dee и Foo :: dum, но почему разница в объявлении? Мне кажется "неопределенным".