wood burning stoves*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Query on covariant return --- SCJP 5.0 Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Query on covariant return --- SCJP 5.0 " Watch "Query on covariant return --- SCJP 5.0 " New topic
Author

Query on covariant return --- SCJP 5.0

Pawanpreet Singh
Ranch Hand

Joined: Jun 12, 2005
Posts: 264

I understood the logic of covariant return types, but the output of this code is not clear

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() {
System.out.println("In B");
return new B();
}
}

Please explain why x=5 is printed instead of 6
Deepak Bala
Bartender

Joined: Feb 24, 2006
Posts: 6662
    
    5

Try this instead.

B b = (B) c.getObject();
System.out.println(b.x);


SCJP 6 articles - SCJP 5/6 mock exams - More SCJP Mocks
Eleanor Leong
Greenhorn

Joined: Mar 24, 2006
Posts: 21
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 ]
Pawanpreet Singh
Ranch Hand

Joined: Jun 12, 2005
Posts: 264

Thanks a lot Elanor.
ram gaurav
Ranch Hand

Joined: Mar 29, 2006
Posts: 208
Hi Eleanor

in the statement like this CovariantTest c = new SubCovariantTest();

Simple methords are call on the base of object , not on the base of the reference , so , getObject() of SubCovariantTest is called.

Thanks
Gaurav
Ajit Amitav Das
Ranch Hand

Joined: Dec 14, 2005
Posts: 49
--------------------------------------------------
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.


Warm Regards<br />Ajit Amitav Das<br />SCJP 1.5
Rajah Nagur
Ranch Hand

Joined: Nov 06, 2002
Posts: 239
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
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."
AkhilSharma
Greenhorn

Joined: Sep 11, 2006
Posts: 1
In the main method we have following code:

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.
wise owen
Ranch Hand

Joined: Feb 02, 2006
Posts: 2023
How does covariant overriding method work?
E McKenney
Greenhorn

Joined: Sep 01, 2006
Posts: 18

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.

Is this right?

b.


SCJP '06
Tom Adams
Ranch Hand

Joined: Feb 07, 2003
Posts: 56
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)


Console:


HTH


Tom
Burkhard Hassel
Ranch Hand

Joined: Aug 25, 2006
Posts: 1274
Hi, cowboys!

Many thanks to wise owen for his link!!!



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
oops, I wrote
And in the original example, a B will be returned, not an A.


Otherway round, as I wrote later
Bu.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Query on covariant return --- SCJP 5.0