Объясните этот вывод

class A {
    private int a = 10;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;       
    }    
}

class B extends A {
    public int a = 20;
}

public class Demo {
    public static void main(String args[]) {
        B a = new B();
        System.out.println(a.getA());        
    }
}

output: 10
поскольку все поля в родительском классе живут в дочернем объекте, есть два поля с одинаковым именем (a), а также геттер и сеттер в дочернем объекте, поэтому как java разрешает этот метод получения и установки для частное поле в родительском классе?


person Kalhan.Toress    schedule 23.03.2014    source источник


Ответы (2)


Метод getA() определен только в суперклассе и может обращаться только к членам суперкласса. Он не может знать о a подкласса, поэтому a подкласса не может его затенять.

Не имеет значения, является ли член a подкласса частным или открытым. Вы увидите такое же поведение, если объявите a закрытым в дочернем классе.

Обновление. Это попытка ответить на более общий вопрос: Как разрешаются элементы, определенные как в родительском, так и в подклассах?

Рассмотрим следующее расширение примера OP:

class A {
    public int a = 10;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;       
    }    
}

class B extends A {
    public int a = 20;
}
class C extends B {
    public int getA() {
        return a;
    }
}

public class Demo {
    public static void main(String args[]) {
        B a = new B();
        System.out.println(a.getA());        

        C c = new C();
        System.out.println(c.getA());        
    }
}

Здесь мы видим выходные данные 10 и 20, которые подразумевают, что метод getA() класса C читает версию a класса B.

Теперь давайте посмотрим, что произойдет, если мы сделаем версию A для B частной.

class B extends A {
    private int a = 20;
}

Если мы попытаемся скомпилировать, мы получим ошибку компилятора:

Demo.java:18: error: a has private access in B

Приведенный выше эксперимент, кажется, предполагает, что каждый класс будет пытаться разрешить a, глядя либо на себя, либо поднимаясь по иерархии классов, пока не найдет первый a. Если этот a ему виден (то есть public или protected), он вернет его. Если этот a не виден, он просто не будет компилироваться.

person merlin2011    schedule 23.03.2014
comment
да правда, спасибо за ответ. но мой вопрос заключается в том, если метод получения и оба поля a (если вы отлаживаете код, вы можете видеть, что есть две переменные, называемые a), живут ли в дочернем объекте, каковы вызовы родительского класса a, каков механизм решения? - person Kalhan.Toress; 23.03.2014
comment
@KalhanoToressPamuditha, я не нашел документации по этому поводу, но я провел быстрый эксперимент. Позвольте мне обновить свой ответ. - person merlin2011; 23.03.2014
comment
@KalhanoToressPamuditha, я думаю, ваш комментарий был отключен. Если вопрос касается html, предлагаю вам задать новый вопрос. :П - person merlin2011; 23.03.2014
comment
: p, @ merlin2011 не могли бы вы объяснить это мне, рассмотрите дочерний объект, он включает методы получения и установки от родителя и a, при вызове метода получения, как он разрешает это a от родителя, что происходит позади? - person Kalhan.Toress; 23.03.2014
comment
@KalhanoToressPamuditha, объект дочернего класса сначала будет использовать методы получения и установки от самого себя. Если они не определены, он будет выглядеть в суперклассе, а затем в суперклассе. - person merlin2011; 23.03.2014
comment
он будет смотреться в суперклассе а потом в суперклассе? как это возможно, потому что у дочернего объекта уже есть эти методы, поэтому нет необходимости искать суперклассы, не так ли? - person Kalhan.Toress; 23.03.2014

Когда вы вызываете getA (), вы вызываете метод A, который возвращает значение переменной A.

Если вы перезапишете getA () в классе B, на выходе будет 20, потому что он получит переменную «a» в контексте B.

Если вы вызовете setA из объекта класса B, он отразится только на атрибутах A. Даже если вы установили переменную B напрямую (из-за общедоступности), результат все равно будет 10.

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

person Aleksandrus    schedule 23.03.2014