0
public class Print1 {
    int x = 1;
    public void print(A a) { System.out.println(x); }
    public void print(B b) { System.out.println(x+1); }
}      

public class Print2 extends Print1 {
    int x = 3;
    public void print(A a) { System.out.println(x); }
    public void print(B b) { System.out.println(x+1); }
    public void print(C c) { System.out.println(x+2); }
}

// a tester class with main method 
A a = new A(); B b = new B(); C c = new C();
Print1 p1 = new Print1();
Print2 p2 = new Print2();
p1 = p2;

 System.out.println(p1.x); // Call 1, p1 is from Type Print1
 p1.print(c); /* Call 2
 //p1 is from Type Print2, print(B b) will be called */`

Class B is a subclass of Class A and C is a subclass of B.

  1. why in Call 1 P1 from type Print1 even though it is referencing to Object of type Print2 and in call 2 it is behaving as reference to Print2-object?

  2. why in Call 2 print(B b) is called from Print2 and not print(C c)?

This is the most confusing things for me so far in Java. Thank you for your help.

darijan
  • 9,725
  • 25
  • 38
Miloud21
  • 3
  • 2
  • 1
    possible duplicate [http://stackoverflow.com/questions/30558552/method-overriding-vs-class-variable-overriding-in-java](http://stackoverflow.com/questions/30558552/method-overriding-vs-class-variable-overriding-in-java) – Amit.rk3 Aug 05 '15 at 14:13

2 Answers2

0

First print works as expected due to variable shadowing.

You have a variable p1 (type Print1) pointing to the object on the heap of the type Print2. Since Print2 inherits from Print1 this is allowed. And you are able to access the variable x of the Print1 because there is no polymorphism for variables, they cannot "override" one another. Your variable type determined what x you wanted to fetch.

It would be less confusing if you would add another variable int y to Print1 class. You could've accessed it as System.out.println(p1.y); without problems.


The second one also works as expected due to polymorphism (through inheritance).

Since print(c) method is executed on an object, the object is obviously of type Print2 (does not matter what the variable type is (Print1 or Print2), you will use the Print2's method. Simply because the Print2's method had overriden the Print1's method.

darijan
  • 9,725
  • 25
  • 38
0

The type of the variable is used to determine the class member that is accessed.

Therefore p1.x refers to the x field in Print1, not the one in Print2. (it would result in a compile time error, if you removed x from Print1.) The x field in Print2 is a different field, i.e. Print2 objects have 2 different int fields.

Also the print(B b) method is used in the expression p1.print(c) since Print1 doesn't have a method print(C c). (It would be a compile time error, if C wouldn't extend B or A.) Since Print2 overrides the implementation of Print1.print(B b), that implementation is used.

fabian
  • 80,457
  • 12
  • 86
  • 114