0

Can someone explain me what is going on here and WHY?

class Base{
    private float f = 1.0f;
    void setF(float f1){ this.f = f1; }
    float getF() {return f;}
    public void xx(){}
}

class Base2 extends Base{
    private float f = 2.0f;

    public void xx(){
        System.out.println(super.getF()+" "+this.getF());
    }

    //float getF() {return f;} //1
    //void setF(float f1){ this.f = f1; } //2

    public static void main(String[]args){
        Base b=new Base2();
        b.setF(3);
        b.xx();
        System.out.println(b.getF());
        System.out.println(((Base)b).getF());
    }
}

Output of this code will be 3 3, 3, 3.

If I uncomment only line 1 with getter, output will be 3 2, 2, 2.

If I uncomment only line 2 with setter, output will be 1 1, 1, 1.

If I uncomment both line 1 and 2 (with setter and getter), output will be 1 3, 3, 3.

        //default output: 3 3, 3, 3
        //with getter: 3 2, 2, 2
        //with setter: 1 1, 1, 1
        //with getter and setter: 1 3, 3, 3

If override a method in a parent class with code in the subclass, that override method can not access the private member variable, even though the overridden method in the parent does. The overriding method in the subclass can call the overridden method in the parent though.

So, it is explain case#4 with both getter and setter, that have access only to Base2 member variable

anastsiacrs
  • 159
  • 4
  • 18

2 Answers2

1

You get 3 3 3 3 because set/get methods modifies Base.f variable:

You get 3 2 2 2 because set change value of Base.f variable but the get method gets value of Base2.f variable.

You get 1 1 1 1 because set method change value of Base2.f variable but the get method gets value of Base.f variable.

You get 1 3 3 3 because super.getF() returns value of Base.f variable but other get methods returns value of Base2.f variable. Also the set method change value of Base2.f variable.

lukaslew
  • 455
  • 1
  • 6
  • 13
  • why in case#1 (without getter and setter in subclass) setF(3) change both Base.f and Base2. f? – anastsiacrs Jul 24 '15 at 11:58
  • @anastsiacrs `setF(3)` change only `Base.f`. Getter and setter is only defined in the `Base` class so when their are executed they get/set value of `Base.f` varaible. The `Base2.f` is not changed that why in case #2 (where you override getter method) you get `3 2 2 2` – lukaslew Jul 24 '15 at 12:20
  • case#1: if setF(3) change only Base.f, than why this.f (in method xx()) return 3? – anastsiacrs Jul 24 '15 at 12:32
  • `Base2` class does not have its version of the `getF()` method so it uses defined in `Base` class method with the same signature. in first example `super.getF()` and `this.getF()` are the same. If you really want to understand what happens you could paste this code into some IDE and debug the code. You could see the variable values and when what method is executed. – lukaslew Jul 24 '15 at 12:41
  • Thx. Now it is clear. I didn't notice that i use this.getF() and super.getF(), but not this.f and super.f – anastsiacrs Jul 24 '15 at 12:48
1

Let's start from some background.

In Inheritance Java tutorial it is stated:

Private Members in a Superclass

A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.

In Polymorphism chapter it is stated:

The Java virtual machine (JVM) calls the appropriate method for the object that is referred to in each variable. It does not call the method that is defined by the variable's type. This behavior is referred to as virtual method invocation and demonstrates an aspect of the important polymorphism features in the Java language.

Finally, in Hiding fields chapter of the same tutorial it is stated:

Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name. Instead, the field must be accessed through super, which is covered in the next section. Generally speaking, we don't recommend hiding fields as it makes code difficult to read.

Thus, subclass has no way to access private members of superclass directly. However, they still exist, and could be accessed or modified using non-private accessors/mutators.

Now back to the question itself.

In your first example, you override neither accessor nor mutator - you just call the inherited ones all the time. They return and modify the value of f of Base. Why inherited accessor/mutator do not return/modify the value of f of Base2? Because even if f of Base was not private, it would not be overridden, but just hidden.

In your second example, you override the accessor. This is where you start to involve polymorphism. This short answer might be helpful to understand it. When you call b.setF(3), you set the value of f of Base. However, when you call getF() you get the value of f of Base2, except for the case when you call it with keyword super. Please note, that in your last call System.out.println(((Base)b).getF()) casting to Base does nothing since b is already declared as Base. You can not call an overridden method of superclass without using super (as you already know, only instance methods can be overridden).

In your third example, you override the mutator. The situation is opposite to your second example. When you call b.setF(3), you set the value of f of Base2. But you always get f of Base from the getter, because the getter is not overriden. Thus, all 4 calls to getF() return the initial value of f of Base.

In you last example, you override both accessor and mutator. Therefore, they operate on f of Base2. The only call that return the initial value of f of Base is obviously super.getF().

This is definitely not a perfect explanation, but I hope it helps.

Community
  • 1
  • 1
Constantine
  • 3,187
  • 20
  • 26