Search code examples
javainheritancebindingconstructortyping

constructor and hiding a filed in Java


I am doing this school exercise, and I couldn't figure why the following two cases would have different results.Can someone explain why in the first case int x of A is 100? Hasn't the int x in C shadowed int x in A? I have commented my question in the code as well. Many thanks!

class A {  // Case 1 
  public int x = 1;
  public String k() { return "A" + this.x; }
 }
class B extends A {
   public int x = 10;
}
class C extends B {
  public int x = 100;
  public String k() { return "C" + this.x; }
}
class TestABC {
  public static void main(String[] args) {
    A a1 = new C();
    C c1 = new C();
 } 
}
System.out.println(a1.x +"," + c1.x);// It prints out 1, 100.
   //However I thought it'd print out 100, 100, as the int x in C shadows int x in A. 

Another Case is

class A1 { //case 2
  int x=10;
  public void method() {
  System.out.print("A:" + this.x + " ");
  }
}
class B1 extends A1 {
  int x=20;
public void method() {
  System.out.print("B:" + this.x + " ");
}
public static void main(String args[]) {
   A1 s = new B1();
   s.method();// It prints out B: 20. 
   //What's the difference between this one and a1.x in the previous example? 
   //Why it prints out the subclass but in the previous code a1.x prints out the parent class?
   }
} 

Solution

  • The first case prints out 1, 100 because it's getting the value of the VARIABLE Something like:

    Get the value of x in A and get the value of x in C
    

    Overriding happens only to METHODS not with VARIABLES. That's why in your second case it invokes the method inside the B1 instead of the A1

    This is called Runtime Polymorphism.


    EDIT 2:

    Let me explain it further:

    When we are invoking a method, at runtime, instead of looking at the reference variable's type, the JVM looks at the object's type and run that method.

    But with variables, it's the other way around, instead of looking at the object's type, the JVM looks at the reference variable's type, and get that variable

    Given the following example:

    class Animal {
    
        String whatAmI = "An Animal";
    
        public void sayHi() {
            System.out.println("Hi from Animal");
        }
    }
    
    class Dog extends Animal {
    
        String whatAmI = "A Dog";
    
        public void sayHi() {
            System.out.println("Hi from Dog");
        }
    }
    

    Sample run:

    //Reference variable type               //Object type
    Animal              anAnimal            = new Animal();
    Dog                 aDog                = new Dog();
    Animal              anotherDog          = new Dog();
    
    anAnimal.sayHi();       //Hi from Animal
    aDog.sayHi();           //Hi from Dog
    anotherDog.sayHi();     //Hi from Dog
    

    We get these output because the JVM invoked the sayHi() method on the Object's type not the Reference variable's type.

    But the thing is, it doesn't work the same way with variables. If we try something like:

    System.out.println(anAnimal.whatAmI);       //An Animal
    System.out.println(aDog.whatAmI);           //A Dog
    System.out.println(anotherDog.whatAmI);     //An Animal
    

    We have these output because the JVM get the whatAmI variable from the Reference variable's type.

    A technique to remember this is to focus on the equal (=) sign.

    • When invoking a method, invoke the method on the right side of the equal (=) sign.
    • When getting a variable, get the variable on the left side of the equal (=) sign.