This week's book giveaway is in the General Computing forum. We're giving away four copies of Arduino in Action and have Martin Evans, Joshua Noble, and Jordan Hochenbaum on-line! See this thread for details.
At compile time : c is an instance of CovariantTest so for c.getObject(), the method public A getObject() should be called. Please note the return is Class A. Class A is the return to this call. I think a temporary reference of Class A is assigned to this call.
At runtime : Due to method public A getObject() is overriden by method public B getObject(), method public B getObject() is actually called and returns an instance of class B.
Now, the temporary reference of Class A is assigned to a Class B instance. When printing variable x, it is the x (value 5) of Class A instance is printed.
Eleanor
(Changed as poster requested) [ July 16, 2006: Message edited by: Barry Gaunt ]
-------------------------------------------------- class A { int x = 5; }
class B extends A { int x = 6; }
public class CovariantTest { public A getObject() { System.out.println("In A"); return new A(); }
public static void main(String[] args) { CovariantTest c = new SubCovariantTest(); System.out.println(c.getObject().x); } }
class SubCovariantTest extends CovariantTest { public B getObject() { //Here either method signature should be changed System.out.println("In B");//for overloading or return type should be same return new B(); //for overridding. } } ------------------------------------------ i think this will give compilation error because it is violating contracts of either method overloading and method overriding , beacuse in SubCovariantTest class the method declared getObject() is having same signature but with different return type so its violating method overriding where both signature and return type should be same , and if return type is same then we don't have different method signature so its violating method overloading also. so this will give a compilation error.
Refer this thread,things will get clarified. This is relevant only to JDK 5.0 You might have used some previous version. [ July 19, 2006: Message edited by: Rajah Nagur ]
You can't wake a person who is <b><i>pretending</i></b> to be asleep.<br />Like what <b>"it"</b> does not like - <i> Gurdjieff </i>
Ajit Amitav Das
Ranch Hand
Joined: Dec 14, 2005
Posts: 49
posted
0
sorry to everyone here , first i used this code in eclipse which is using jre1.4 , thats why it was coming comilation error , but in jdk1.5 it is allowed , method binding and data member binding are different , there is no concept of datamember overriding it is just hiding .Imporant point to note here is "when an instance method is invoked on an object using a refernce it is the class of the current object denoted by the object not the type of reference that determines which method implementation will be executed.But incase of a field(data member) of an object is accesed using a reference, it is the type of reference not the class of the current object denoted by the reference that determines which field will actually will be accessed."
CovariantTest c = new SubCovariantTest(); System.out.println(c.getObject().x);
Change the code to:
CovariantTest c = new SubCovariantTest(); B d = c.getObject();
In the getObject() method add println's to print which method version is being executed. Try compling now...
And what do we get:
found : A required: B B d = c.getObject(); ^ 1 error
So it means that the method which is shown to return B type object is actually returning A type.
Now change the code in main to:
CovariantTest c = new SubCovariantTest(); c.getObject();
And run it. The println statements which you have added still tell you that code which ran is subclass version (polymorphic call) and we should actually get a B type of object rather than A, but we need to understand that the getObject() method in CovariantTest class is is declared to return A so even when the actual class returned is B, it is still being referred as A and hence when we try to print x value it prints value from class A rather than B.
So if I'm understanding this right, our main clue is that the code directly references a class member rather than a method.
E.g. if classes A and B had a getter method to return the value of x, and the main routine called that method instead of simply saying ".x", we'd get 6 after all.
The point here is not about covariant returns - it is about what members of an object are poloymorphic (ie. Ajit's post). Only instance methods are poloymorphic - meaning they use run time binding, all other members are based only on the reference type.
Slightly changed example (removing some of the red herrings)
I think it is NOT possible to understand the output of the code (see start of this thread) UNLESS you know what this synthetic bridge is.
Tom's first sentence
The point here is not about covariant returns - (...)
can be a bit misleading, as it refers to his example, not to the original problem.
Correct me if I'm wrong: The problem of the code (at the beginning of the thread) has nothing to do with the different behaviour of variables and non-static methods regarding polymorphism in the first place.
It is all about this synthetic bridge thing and covariant returns.
And in the original example, a B will be returned, not an A. To test this, I put a bug into the code. Therefor the code below will NOT compile. Due to this synthetic bridge thing, calling getObject() polymorphically, an A and NOT a B will be returned. Without the problem line, it will output: Covariance Demo Child gimme an A!
Yours, Bu.
slightly adapted:
all events occur in real time
Burkhard Hassel
Ranch Hand
Joined: Aug 25, 2006
Posts: 1274
posted
0
oops, I wrote
And in the original example, a B will be returned, not an A.
Otherway round, as I wrote later Bu.
I agree. Here's the link: http://ej-technologies/jprofiler - if it wasn't for jprofiler, we would need to
run our stuff on 16 servers instead of 3.