Унаследованный метод Java вопрос - PullRequest
1 голос
/ 15 декабря 2009

Во время подготовки к экзамену SCJP 6 я столкнулся с этим вопросом на тестовом экзамене:

class A{  
    private static String staticProperty = " a ";  
    String getStaticProperty() { return staticProperty; }  
}  

class B extends A {  
    private static String staticProperty = " b ";  
    public static void main(String[] args){  
        new B().go(new A());  

    }  
    void go(A t){  
        String s = t.getStaticProperty() + B.staticProperty + staticProperty + (new B().getStaticProperty());  
        System.out.println(s);  
    }  
}  

Какой вывод ??

Вывод здесь a b b a

Я прекрасно понимаю a b b, но не понимаю "а" в конце. Если вы унаследуете метод (в этом случае B наследует getStaticProperty () от A), и этот метод возвращает статическую переменную из родительского объекта (staticProperty), которую вы переопределяете в дочернем элементе, вы ВСЕГДА будете использовать родительскую статическую переменную значение??

Кстати, удаление статического идентификатора и превращение staticField в экземпляр класса возвращает те же результаты. Изменение модификаторов доступа из частного в общедоступное или другое возвращает те же результаты. Мне нужно было переопределить метод getStaticProperty, чтобы получить то, что я хотел увидеть.

Ответы [ 5 ]

4 голосов
/ 15 декабря 2009

Доступ к полям не подлежит динамической отправке , как доступ к методу, то есть поля не могут быть переопределены. Эта строка в классе A:

String getStaticProperty() { return staticProperty; }  
Поэтому

относится к полю staticProperty в классе А. Поле класса B с тем же именем не имеет значения, или, скорее, оно: скрывает поле суперкласса, и весь код в классе B будет использовать это поле , В руководстве Sun по Java есть что сказать по этому вопросу:

Внутри класса поле, которое имеет то же имя, что и поле в суперклассе скрывает поле суперкласса, даже если их типы разные. В пределах подкласс, поле в суперклассе нельзя ссылаться на его простой название. Вместо этого поле должно быть доступ через super, который рассматривается в следующем разделе. В общем-то говоря, мы не рекомендуем прятаться поля, поскольку это делает код трудным для читать.

3 голосов
/ 15 декабря 2009

new B().getStaticProperty() вызывает метод из A, который возвращает статическое свойство A, поскольку он имеет область действия A.

1 голос
/ 15 декабря 2009

Размышляя о таких проблемах наследования, как эта, вам может быть полезно подумать о том, что происходит, когда вызывается new B(). Когда конструктор B выполняется, первая операция, которую он выполняет (поскольку явного вызова конструктора A нет) - super(). В этот момент создается экземпляр A, и в этом объекте метод getStaticProperty() явно ссылается на staticProperty. Затем запускается тело конструктора B (опять же, только после успешного выполнения конструктора A), и, поскольку он ничего не делает для изменения или переопределения метода getStaticProperty(), который был создан конструктором A, он, безусловно, не меняет поведение этого метода либо.

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

1 голос
/ 15 декабря 2009

Функции являются виртуальными в Java, но члены класса (статические или экземпляры) - нет. Таким образом, хотя определение B staticProperty может маскировать определение A, оно не отменяет его.

// in B
String fromChild = staticProperty; // == "b"
String fromParent = A.staticProperty; // == "a", was masked but not overridden

Единственный способ получить A для доступа к переменной, определенной в B, - это определить функцию-получатель в A и переопределить ее в B, как вы предлагаете.

0 голосов
/ 15 декабря 2009

getStaticProperty () - это метод, определенный в классе A. Метод не переопределяется в классе B, поэтому используется метод из класса A. Поскольку A никак не может видеть статическое свойство B, он возвращает свое собственное значение.

...