Почему значение a в базовом классе не меняется?

#java #variables #inheritance

Вопрос:

поэтому я пытаюсь понять, как именно наследование работает в java. я хочу обновить значение a в суперклассе с помощью метода второго класса. и я хочу распечатать обновленные данные, используя метод из третьего класса. Но я не получаю обновленные данные, я все еще получаю 10 в качестве выходных данных, хотя я изменил их на 20, используя метод обновления во втором классе. почему это происходит? как я могу это решить?

код:

 class one{
    int a=10;
}
 
class two extends one{
    void update(){
        super.a=20;
    }
}

class three extends one{
    void print_changed_data(){
        System.out.println(super.a);
    }
}

public class four{
    public static void main(String[] args) {
        two obj2=new two();
        obj2.update();

        three obj3=new three();
        obj3.print_changed_data();
    }
}
 

Комментарии:

1. он действительно изменился, но вы изменили его для своего экземпляра obj2, а не для obj3. Понимаете ли вы разницу между статикой и экземпляром?

2. Наследование работает не так, класс three -это новый экземпляр, который ничего не знает о том, что класс two сделал a в своем экземпляре. Класс two и класс three имеют разные экземпляры a .

3. Может быть, вы хотите сделать переменную a в классе one доступной для ее подклассов, используя ключевое слово protected?

4. @Stultuske вы можете дать мне точный код?

5. @LuckBandit74 Я бы сказал, что лучшей практикой было бы сделать его закрытым и создать сеттер и метод получения для доступа к свойству за пределами класса.

Ответ №1:

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

 two obj2=new two();
// obj2 = {
//     a = 10
//     update()
// }
obj2.update();
// obj2 = {
//     a = 20
//     update()
// }

three obj3=new three();
// obj2 = {
//     a = 20
//     update()
// }
// obj3 = {
//     a = 10
//     print_changed_data()
// }
 

Вот лучший пример того, для чего используется super:

 class one{
    int a=10;

    void update(){
        a = 30;
    }
}

class two extends one{

    void update(){
        a=20;
    }

    void print(){
        // a = 10
        System.out.println(a);
    
        this.update(); // a = 20
        System.out.println(a);
    
        super.update(); // a = 30
        System.out.println(a);
    }
}

public class three{
    public static void main(String[] args) {
        two obj2=new two();
        obj2.print();
        // output
        // 10
        // 20
        // 30
    }
}
 

Ответ №2:

Я думаю, вы неправильно поняли, что происходит в наследовании между этими 3 классами. Каждый раз, когда вы создаете новый экземпляр класса, используя new в своем примере, вы создаете новую переменную экземпляра, вызываемую a в этом классе, которая начинается со значения 10. В классе Two у вас есть вызываемый метод экземпляра update() , который изменяет значение a на 20, вызов этого метода будет обновляться только a для экземпляра класса, в котором вы его вызываете; в этом случае obj2 .

 class One{
    int a=10;

    void print_changed_data(){
        System.out.println(a);
    }
}
 
class Two extends One {
    void update(){
        super.a=20;
    }
}

class Three extends One {

}

public class four{
    public static void main(String[] args) {
        One obj1 = new One();
        obj1.print_changed_data(); // Prints 10

        Two obj2 = new Two();
        obj2.print_changed_data(); // Prints 10
        obj2.update();
        obj2.print_changed_data(); // Prints 20

        Three obj3 = new Three();
        obj3.print_changed_data(); // Prints 10
    }
}
 

В приведенном выше примере я внес изменения в ваш код и создал 3 объекта obj1 , obj2 и obj3 . obj1 и obj3 всегда будет выводить 10 при вызове print_changed_data() , потому что вы еще не обновили a новое значение. В то время как при вызове update() obj2 вы меняете obj2 a значение s на 20.

Ознакомьтесь с этим простым руководством w3schools по наследованию

Ответ №3:

Классы-это просто чертежи; у них нет никакого хранилища. При инициализации класса создается объект со всеми необходимыми переменными. obj2 и obj3 являются просто разными объектами в памяти, содержащими их отдельные переменные. Между и нет «прямой» связи class two class three . Оба класса используются class one в качестве схемы, но это не создает связи между переменными ( a ) в объектах.

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