0

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?
   }
} 
user3735871
  • 527
  • 2
  • 14
  • 31
  • There is a discussion of this matter here: http://stackoverflow.com/questions/17303662/dynamic-binding-works-for-methods-why-not-for-other-members-variables and here: http://stackoverflow.com/questions/10722110/overriding-variables-java – galusben Sep 12 '14 at 05:04

2 Answers2

1

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.
lxcky
  • 1,668
  • 2
  • 13
  • 26
  • So in the first case, when a1 is initiated using "A a1= new C();", it contains int x= 1 , but not int x= 100 as a class C object? Thanks! – user3735871 Sep 12 '14 at 05:18
  • Thank you for the answers! Just one more question: so in the second case, s still contains int x= 10? If so when the method() System.out.print("B:" + this.x + " "); is called, what does "this" refer to? – user3735871 Sep 12 '14 at 05:32
  • 1
    On the second case x refers to 20 because in your `System.out.print()` method, you use `this` and remember, `this` refers to the *currently executing* class. Which in this case is C, so we get the value of C's x. – lxcky Sep 12 '14 at 05:34
  • Sure, thank you! You mean in the second case, in method System.out.print() refers to class B1, and even though there is no object that contains int x= 20, but B1 is still the executing class, so the variable int x= 20 is used? – user3735871 Sep 12 '14 at 05:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/61097/discussion-between-j-lucky-and-user3735871). – lxcky Sep 12 '14 at 07:28
1

Yes.. This is runtime polymorphism or overridding.

Case 1: A a = new C(); Case 2: C c = new C();

Rules of polymorphism:

                                          Variable            Method          Static Method
Reference of Superclass(Case 1)             Super               Sub               Super
Reference of Subclass(Case 2)                Sub                Sub                Sub

These are the rules of polymorphism. So if you create any member variables of these types, you will always see results in this format.

Hence the result you see.

richa_v
  • 119
  • 1
  • 7