• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Query on covariant return --- SCJP 5.0

 
Ranch Hand
Posts: 264
Eclipse IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Bartender
Posts: 6663
5
MyEclipse IDE Firefox Browser Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Try this instead.

B b = (B) c.getObject();
System.out.println(b.x);
 
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 264
Eclipse IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks a lot Elanor.
 
Ranch Hand
Posts: 208
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
--------------------------------------------------
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.
 
Ranch Hand
Posts: 239
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Ajit Amitav Das
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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."
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 2023
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How does covariant overriding method work?
 
Greenhorn
Posts: 18
VI Editor Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 1274
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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:
 
Burkhard Hassel
Ranch Hand
Posts: 1274
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
oops, I wrote

And in the original example, a B will be returned, not an A.



Otherway round, as I wrote later
Bu.
 
Put a gun against his head, pulled my trigger, now he's dead, that tiny ad sure bled
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic