Win a copy of Design for the Mind this week in the Design forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

calling the right variable and method

 
Rob Petterson
Ranch Hand
Posts: 149
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Question ID 953430671680
public class TestClass
{
public static void main(String []args)
{
A o1 = new C( );
B o2 = (B) o1; //1
System.out.println(o1.m1( ) );
System.out.println(o2.i );
}
}
class A { int i = 10; int m1( ) { return i; } }
class B extends A { int i = 20; int m1() { return i; } }
class C extends B { int i = 20; int m1() { return i; } }
The answer is 30,20
I was in two minds as to this question.
I reasoned that it would produce the above result, however I had this doubt in my mind that it would throw a ClassCastException, due to line 1.I thought it would compile but would fail at runtime. Anyone explain?
 
Valentin Crettaz
Gold Digger
Sheriff
Posts: 7610
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First off, the printed result is 20,20 and not 30,20.
The fact is that o1 is a reference of type A pointing to an object of runtime type C. Then, o1 is cast to B and referenced by o2 (of type B) which is perfectly legal. It is always allowed to reference an object of a subtype with a reference variable of a supertype. In clear, a C is_a specialization of a B which in turn is_a specialization of a A.
Then, the method m1 is resolved according to the runtime type of the variable, i.e. C. Field access is resolved according to the declared type of the variable (i.e. B).
 
Rob Petterson
Ranch Hand
Posts: 149
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm still confused with your answer.
If you removed: A o1 = new C();
would: B 02 = (B) o1; be legal?
 
Valentin Crettaz
Gold Digger
Sheriff
Posts: 7610
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If your remove that statement, where does o1 come from? I mean, in the second statement we have o1 and it has to be declared somehow...
 
Paul Villangca
Ranch Hand
Posts: 133
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Of course not, 'coz then o1 wouldn't be declared.
It's easier to understand your code line by line.

A o1 = new C( );
Here, a reference of type A points to an object of type C, which is legal, since C is a subclass of A.

B o2 = (B) o1; //1
Here, o1 (which is a reference of type A) gets assigned to o2 (a reference of type B.) The cast is required since A is a superclass of B. At runtime, since o1 points to an object of type C (which is a subclass of B), it doesn't generate any ClassCastException.

System.out.println(o1.m1( ) );
Then, the method m1 is resolved according to the runtime type of the variable, i.e. C.

This means that the m1() method of C (the object pointed by o1) will execute, returning 20.

System.out.println(o2.i );
Field access is resolved according to the declared type of the variable (i.e. B).

Here, class B's i variable is returned.
 
Rob Petterson
Ranch Hand
Posts: 149
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

[ June 19, 2002: Message edited by: Rob Petterson ]
 
Valentin Crettaz
Gold Digger
Sheriff
Posts: 7610
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
true, but the type of the object referenced by the variable must be assignment compatible with the variable to which it is assigned. In clear, o1, although having a declared type of A, is in fact and object of type C. Thus, an object of type C can be cast to B without any problem.
The problem mentioned in RHE can be shown with the following example:
A o1 = new A();
B o2 = (B) o1;
In this case, the compilation would be successful but at runtime you would get a ClassCastException since an object of runtime type A cannot be referenced by a variable of type B.
Casting is always allowed by the compiler since casting is a way of telling the compiler "I know what I'm doing, believe me."
 
Rob Petterson
Ranch Hand
Posts: 149
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Right, I think it's sinking in.
I'll need to practice with it though.
Thanks for your help.
 
Valentin Crettaz
Gold Digger
Sheriff
Posts: 7610
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'll need to practice with it though.
Right, practicing is the key to understanding. Don't hesitate to ask questions when in doubt
 
Francisco A Guimaraes
Ranch Hand
Posts: 182
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Valentin, I have a doubt: in the first example, if you print o1.i you�ll get 10, why do you get 20 when you print o1.m1() ?
 
Valentin Crettaz
Gold Digger
Sheriff
Posts: 7610
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because, as I said above, access to a variable is resolved according to the declared type of o1 and access to a method is resolved according to the runtime type of o1.
In A o1 = new C() the declared type of o1 is A and the runtime type of o1 is C. Thus, o1.i is 10 and o1.m1() yields 20.
[ June 20, 2002: Message edited by: Valentin Crettaz ]
 
Deepali Pate
Ranch Hand
Posts: 114
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This i guess is what is called polymorphism in Java.
It states that variables are bound at compile time and methods are bound at runtime.
Considering the expample. At compile time the compiler only sees that o1 is of class type A it does not see that it is of type A but actualy holding type c. And since variables are bound at compile time it picks variable i from class A if u would print o1.i.
A o1 = new C( );
But if u asked to print o1.m1() it would print the value from C. Becoz at runtime it actually notices that o1 is of type C so it picks method from there.
This is very imp concept for exam. So get it cleared if u are palnning to take exams.
 
Francisco A Guimaraes
Ranch Hand
Posts: 182
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I know that, but the method m1() returns i and i in o1 is 10 because o1 is of declared type A, so shouldn�t it return 10? or there are two values of i depending on how you call it?

Francisco
 
Valentin Crettaz
Gold Digger
Sheriff
Posts: 7610
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Francisco,
note that each member variable i is local to the class it is declared in... method m1() of class B will return the value of the member i declared in class B. The same applies to A and C.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic