• 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

Covariant Return Types

 
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The following code:

class A
{
int x=5;
}

class B extends A
{
int x=6;
}

public class CovariantTest
{
public A getObject()
{
return new A();
}

public static void main(String args[])
{
CovariantTest c1 = new SubCovariantTest();

System.out.println(c1.getObject().x);
}
}

class SubCovariantTest extends CovariantTest
{
public B getObject()
{
return new B();
}
}


The answer given is 5 though i feel is should have been 6.

Can someone please clarify this.

Thanks in advance.
 
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The "int x" declaration in class B "shadows" the one in class A, and thus does NOT participate in the inheritance.

If class B simply inherited "x" instead of declaring its own version, the result would be what you had expected.
 
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 do covariant overriding methods work?
 
Ade Barkah
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry, but the explanation provided in that link is wrong. This issue has nothing to do with covariant returns really.

For example, if we modify SubCovariantObj.getObject() to return A instead of B (so there is no covariant return at all), the answer would still be the same.
 
wise owen
Ranch Hand
Posts: 2023
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Check this thread.
 
Ranch Hand
Posts: 463
Eclipse IDE Tomcat Server Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The correct answer I believe is OVERRIDING will NOT be applied to variables. What variable to access in the above case is decided based on Reference type and NOT on actual type.

Try adding code to return x, like int getX() { return x; } in each class A and B, and call that getX() instead of directly showing x, it will print 6.

Hope this clears your doubt.

- Surya.
 
Ade Barkah
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Right!

wise owen: Try it yourself. Modify SubCovariantObj.getObject() to return A instead of B, i.e., "public A getObject()", so there is no covariant return, and therefore no "synthetic bridge".

How come the result is still the same? Because covariant returns has nothing to do it this issue!

Maybe we should review this link instead.
 
wise owen
Ranch Hand
Posts: 2023
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Instance variables, static variables, static overridden methods (it looks like it's an override, but actually hidden), and overloaded methods are all bound at compile time.

Compiler need to know what "c1.getObject()" is for "x". Calling getX() is Run time binding and this kind of binding depends on the instance object type.
 
Ranch Hand
Posts: 1274
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Objection, your honor!


Ade Barkah wrote:

Sorry, but the explanation provided in that link is wrong. This issue has nothing to do with covariant returns really.




Well it has. And it has nothing to do with shadowing.
If you have
CovariantTest c1 = new SubCovariantTest();
in the main method, and you call
getObject()
on c1, then the synthetic bridge (see link of wise) will come into play.

The object returned by getObject will be an A, not a B.
The code will not compile if you add
B test = c1.getObject();
into your main method

A test = c1.getObject();
would be fine.




Yours,
Bu.
 
Ade Barkah
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Then please explain why the code below, which has NO covariant return, and therefore no bridging method whatsoever, still return the SAME result.

You can't have it both ways.

 
Ranch Hand
Posts: 2412
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Ade Barkah:
Then please explain why the code below, which has NO covariant return, and therefore no bridging method whatsoever, still return the SAME result.

You can't have it both ways.



Because the method you provided has the same return type as the bridge method.

This is the result of javap on the original SubCovariantTest.

 
Ade Barkah
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Nah, the modified example I provided above would return the same result even under JDK 1.4. :roll:

The behavior hasn't much to do with covariant returns, then, obviously if the same exact result can be obtained: a) when covariant return is used; b) when covariant returned is not used; and c) under a JDK when covariant returns didn't even existed.
 
Keith Lynn
Ranch Hand
Posts: 2412
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But the SubCovariantTest program wouldn't compile under 1.4.
 
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
Hi ranchers,


Ade Barkah wrote:

Nah, the modified example I provided above would return the same result even under JDK 1.4.


Your example is irrelevant as there are only A reference types returned.
The real question is, what the lines



do.

The real question is: What will c1.getObject() return, an A or a B?
I'm speaking about reference type (or compile type), not about the type of the object. And reference type surely is a matter of covariance.

The key is, that c1.getObject() returns an A-type and not a B-type as you would expect in the first place.
I said it again, try

after the above lines.
It will not compile, as the super class A will be returned.

The fact that

will produce two fives has never been debated.



Yours,
Bu.
 
Ade Barkah
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I guess we can agree to disagree. My last reply to this topic.

I leave you with a piece of code below... which is ALL that is actually happening. The rest of the fluff (covariant, bridging, etc.) are simply red-herrings. Feel free to use any JDK.



Result: 5
 
Keith Lynn
Ranch Hand
Posts: 2412
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I fail to see the relevance of that code. You're simply demonstrating that instance variables are hidden, not overridden.
 
Ade Barkah
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ooops, sorry Burkhard replied while I was typing.

Burkhard: you write "The key is, that c1.getObject() returns an A-type and not a B-type as you would expect in the first place."

No, in fact c1.getObject() returns a B-type, as one would normally expect. Please verify this yourself.

 
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
Ade Barkah wrote:

... which is ALL that is actually happening. The rest of the fluff (covariant, bridging, etc.) are simply red-herrings. Feel free to use any JDK.



Yep!




;-)

Bu.
 
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
Ade Barkah wrote also:

No, in fact c1.getObject() returns a B-type, as one would normally expect. Please verify this yourself.





c1.getObject returns an object of type B, whose reference type is A (and not B).
This can be stored into reference type Object, sure.
And prints out B@hash something, sure.

But



Compiler says:


The second line cannot compile, because the reference type of c1.getObject() is A.
The last line compiles, cause the object returned here is of reference type A, with an object type of B. But that the object type is B was also printed out in Ade's code above already.
And never been debated, as the output of the original post (see way above) depends only on the reference type, not the object type.



Yours,
Bu.
 
reply
    Bookmark Topic Watch Topic
  • New Topic