aspose file tools
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Covariant returns Big Moose Saloon
  Search | Java FAQ | Recent Topics
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Reply Bookmark "Covariant returns" Watch "Covariant returns" New topic
Author

Covariant returns

Gordy Bone
Ranch Hand

Joined: Feb 25, 2007
Posts: 31


This code prints 5, because x1.getObject returns a new A.

My stupid brain tells me it should return a new B, because Y overrides X's getObject method (using a covariant return). Please explain.

Thanks,

Gordy


SCJP 5, SCWCD 5
Remko Strating
Ranch Hand

Joined: Dec 28, 2006
Posts: 893
You're right that Y extends X and that you're overriding method getObject() in Y from X. This method is also called.

By overriding the JVM also calls the method getObject within Y which is the runtime type. This method returns Object B which is a referance to Object A.
This method returns 5 from Object A, because polymorphic method invocations apply only to instance methods and not to static methods and variables.

I hope is explanation helps.


Remko (My website)
SCJP 1.5, SCWCD 1.4, SCDJWS 1.4, SCBCD 1.5, ITIL(Manager), Prince2(Practitioner), Reading/ gaining experience for SCEA,
Dustin Johnson
Greenhorn

Joined: Nov 14, 2006
Posts: 22
This is one of those tricky things, which is a perfect case of where encapsulation should be used. If you put this code into an IDE, i.e. Eclipse, and throw it in debug mode you will actually see that there are two variables created here... a(a) and a(b). This is because you do not override variables in a subtype, you actually hide them... it's a slightly different concept.

Therefore, you are correct that you get back an object of B(), however your reference variable is of type A. So the program thinks you want the variable from an A object, and gives you the a(a) version. Now, if you actually use getters and setters, you will see that the application will perform more as expected, try this code where I just added comments, and used a getter method instead of trying to directly call the variable:



SCJA 86%<br />SCJP 5.0 98%<br />SCWCD 1.4 79%<br />SCBCD 5.0 83%<br />--------------------------------<br />"I drank what???" - Socrates
Gordy Bone
Ranch Hand

Joined: Feb 25, 2007
Posts: 31
Remko,

Many thanks for your reply.

I get the polymorphic invocation issue the instance variable issue.

The thing I'm struggling with is, given that it's a B object that's returned by the method that's actually called at runtime (i.e. Y's getObject()), why is this an A?

Gordy Bone
Ranch Hand

Joined: Feb 25, 2007
Posts: 31
Thanks, Dustin!
Keith Lynn
Ranch Hand

Joined: Feb 07, 2005
Posts: 2341
Originally posted by Gordy Bone:
Remko,

Many thanks for your reply.

I get the polymorphic invocation issue the instance variable issue.

The thing I'm struggling with is, given that it's a B object that's returned by the method that's actually called at runtime (i.e. Y's getObject()), why is this an A?



If you take a look at the methods created in the bytecode, you can see a little better what is happening.



Notice that in the Y class, there are two methods listed with name getObject, one with return type B, and one with return type A.

In previous versions of Java, an overridding method had to have the same return type as the overridden method.

But now with covariant returns, you can modify the return type.

So what's happened is that an extra method has been inserted into Y that has return type A. This method is called a bridge method and simply invokes the overridden method in B.

The bridge method only becomes important when the type of reference used to invoke the overridden method is a superclass reference.

Since the reference type is X, and X defines a method called getObject with return type A, the bridge method in Y, which also has return type A, is used to call the overridden method.

So the overridden method is still called, but its called through a method with return type A, so that is why the object returned from getObject has reference type A.
Gordy Bone
Ranch Hand

Joined: Feb 25, 2007
Posts: 31
Thank you for that explanation, Keith. I was just about to post another query, but I get it now.

Cheers!

Gordy
Kunal Gupta
Greenhorn

Joined: Mar 10, 2007
Posts: 6
Dear Keith,
I am still not very clear with your explaination.
DO you mean to say that an overridden method is called with the prototype of an inherited one?
These things are not explained in K&B's book..By going by the book I would definitely go with the answer to be the instance variable(a) of class B and not of class A

Oops..I am in a fix..
Keith Lynn
Ranch Hand

Joined: Feb 07, 2005
Posts: 2341
In some cases, an overridden method has the same return type as the overriding case. So it is clear what method to call.

In all cases, the reference type decides which methods are allowed to be called.

In this example, the reference type is of type X. X only has a method named getObject() with return type A. However, since the overriding class modifies the return type, there is no version of getObject() with return type A in Y. So the compiler adds one that simply acts as a bridge.

When a reference of type X is used to call getObject() on an instance of type Y, then the method with return type A in Y is called. But this method just calls the overridden method getObject().

The variable returned is of runtime type B.

But the reference type is type A.
 
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.
 
subject: Covariant returns
 
Similar Threads
Query on covariant return --- SCJP 5.0
Covariant Return Types
Any one solve it?
Problem in polymorphism
Covariant Question