• 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

overriding and covarient return types in java

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

this code's output is B m() 5.But why it isn't B m() 6.i think p.m()will invoked B m() since B m() overrides A m().


 
Ranch Hand
Posts: 446
1
Eclipse IDE MySQL Database Tomcat Server
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
QuoteYourSources and UseCodeTags
 
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

dasun sam wrote:

this code's output is B m() 5.But why it isn't B m() 6.i think p.m()will invoked B m() since B m() overrides A m().




Hi Dasun,
p.m() will return B, because method to call is determined by the actual object during runtime (this applies only to overriding). But you can NOT override variable, thus object B gives You inherited variable x.

Hope this helps.
 
Bartender
Posts: 543
4
Netbeans IDE Redhat Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's what I think:

Method signatures are chosen at compile time. At compile time, you're using an A reference to call a shadowed variable x.

At runtime, through covariant returns, the JVM calls the overriden method, but variables are not overriden, which means the variable is decided on at compile time.
 
dasun sam
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
the method B m() returns the reference of a type B.so i think B.x mean x in class B.

case (1)

B b=new B().
b.x-->6

but

case (2)

A b=new B();
b.x-->5

i think what happend in p.m().x is same as case 1.then it should be print 6.but it didn't happen.
 
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Welcome to JavaRanch. You pose an interesting question. Below is your code just
renamed a bit. At compile time, the compiler has only the type of 'p' to use when
resolving 'x' and it chooses Alpha.x. If you change Alpha.x to private access you
will see the compiler complain. Also, if you change 'p' to type Child you see the
behavior you expected. I'm sure someone else will explain to us just how the
compiler decides which 'x' to use. Jim ... ...

Also, for good looking code in your posts, please investigate now to use code tags.
They look like this (without the '-e' characters): [code-e]your-code-goes-here[/code-e]
 
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think I know why:

Reference p is a Parent reference. Therefore, method's p.m() contract is to return a A.

Object p is a Child. Therefore, it is called the method in Child, which returns a B.
However, p.m() returns a A reference towards a B object, so the x in A is taken, rather than the x from B.

Try changing the declaration of p:




I like this kind of problems!
 
Jim Hoglund
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Valentin : I agree, but it seems a bit sneaky because you might reasonably
expect that since Beta.x hides Alpha.x, its value would still be chosen by the
compiler. But since 'x' is not a member of either Parent or Child, the compiler
apparently digs into the methods of Parent, sees references to Alpha and
decides to pick the 'x' value from there. Boy, this seems like a stretch to me!

Jim ... ...
 
dasun sam
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i think at runtime in heap there is a two objects.

(1)the object that has it's type as Child.this Child object is referenced by the p reference variable that has a type of Parent

(2)the object that has it's type as B.This object has two instance variabels.

--------my points----------
*we are pointing the x variable in (not inherited one) in B type object by using p.m().x
*here p.m().x is same is new B().x.

am i correct?
 
dasun sam
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
can someone give me a better explanation for my problem?
 
Ranch Hand
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This effect is very similar to overriding(the correct term though is 'hiding'/'shadowing') static methods.
http://faq.javaranch.com/java/OverridingVsHiding
 
Vinoth Kumar Kannan
Ranch Hand
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
For the current problem, you can see question 42(& its output) in http://www.mydeveloperconnection.com/html/JavaTrap.htm
Just see if it helps.
 
Jim Hoglund
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Do my experiment above and you will see that it is the compiler that
chooses A.x rather than B.x, not the run-time system. I don't know why
so I hope that a more experienced JRancher can explain it to us.

Jim ... ...
 
Dieter Quickfend
Bartender
Posts: 543
4
Netbeans IDE Redhat Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey Jim,


check out my post from earlier. What do you think?

What we know is:

Methods can be overriden, variables can't. They're shadowed, but not overriden. The fact that methods can be overriden, is the reason that, at runtime, the JVM will run the method of the actual object rather than its reference variable. That is what an override is all about.

Now, if in this case the A reference chose the B variable for no reason but the Object being B... Then how would that not constitute an override?
But we've read so many times already, that variables cannot be overriden. So it's consistent that this method chooses A.x over B.x. This whole exercise is just a creative way to show that gigantic difference between methods and variables.
 
Vinoth Kumar Kannan
Ranch Hand
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Jim, consider..

All overridden methods invoked on 'base' will actually invoke those methods on SubClass class, for any normal method it will invoke BaseClass class's methods.

Now, if you have a overridden static method in SubClass, and you try to invoke that method with 'base' reference, you will actually end up calling the static method in BaseClass - this is because, in Java static methods cannot be overridden, they can only be hidden(hiding). JVM resolves which static method to be called with the reference type & not the object type.

Similarly, if you override a public variable in your SubClass, and invoke that variable on 'base' reference, the variable in the BaseClass will be called - because you are not overriding, but hiding. JVM resolves which instance variable to be called with the reference type & not the object type.

You can only hide/shadow static methods and instance variables, but not override them, in Java.
 
Vinoth Kumar Kannan
Ranch Hand
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is what the JLS says about whatever we are discussing right now...
http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#229119
 
dasun sam
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
then according to the jsl

(1) p.m() will invoke-->B m(){--}
(2)in B m(){--} we create a object of type B and return a B type reference.that mean p.m() will return a B type reference.
(3)according to thr jsl in the object that made in B m(){--} has two int variabels with same name(x).
(4)we here use B type reference(because p.m()will give B type reference)to access above mentioned variabels(instance variabels).
(5)so then considering the declared type(B) p.m().x should be 6 because in class B we declare it as int x=6

**but the output is 5???****
 
Jim Hoglund
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Valentin : I think you've got it. The compiler has to resolve (p.method().x) and
starts with the type of 'p' which is Parent. It then sees that 'A' is the return type of
Parent.method() and therefore chooses A.x. At run-time, however, Child.method()
is called. Its println() shows 'B' first, just ahead of value A.x, or 5. Spooky! Thanks!

Jim ... ....
 
Jim Hoglund
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Valentin's explanation above works for me. How about the rest of you?

Jim ... ...
 
Valentin Musoiu
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello, again!

Sorry for being too succint a few hours ago. I was in a hurry to get to the football pitch

So... We have classes Parent and Child (which, surprisingly extends Parent) and clases Alpha and Beta (Beta extending Alpha).
Child overrides method m inherited from Parent, and uses a covariant return type (Beta, instead of Alpha).

The whole matter is what we get when we take a Parent reference, pointing to a Child object and call on it the m method. If we get an Alpha reference the instance variable declared in Alpha gets printed. If we get a Beta reference, the instance variable declared in Beta (which hides the Alpha inherited variable) gets printed. I think this should be clear for everybody.

I argue that we get an Alpha reference. And I added that it is a Beta object... but that really doesn't matter... It would have mattered if we called an overriden method on the reference. But we don't. We ask for an instance variable. Which is taken from the reference type, not the object type (hiding vs. overriding).

Now... why do we get an Alpha reference? Because it is the return type of the method chosen at compile time.
Subchapter 15.3, although seems impossible to read, sheds some light over the way a method is chosen at compile time/runtime to those eagger enough to finish reading it. I took the snippet that interests me:

The following compile-time information is then associated with the method invocation for use at run time:
(...)
• The result type, or void. (...)


JLS 15.12.3

So, the result type is a compile-time issue. And, at compile time, no object type is known, only the reference type. And p is a Parent. So, the method p.m returns an Alpha. And that is not changed at runtime, as the JLS states. Therefore p.m() returns a Alpha reference. Therefore p.m().x is the x from Alpha!!!

Remember: covariant return types is something introduced recently. It's a relaxing of the rigurous overriding rules. And, generally, the recent changes try not to change how the existent code acts. p.m() returned an Alpha reference when there were no covariant return types. And it still does now!

Hope this time is clearer!
 
dasun sam
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
jim:

according to your explanation

(1) you said at compile time A.x is chosen by the compiler by looking at p's type(Parent)
(2) but at runtime B m() will return B type reference and actually that reference is used to access B type object's(made in B m(){}) instance variabels.
(3)so i think jvm is neglect the thing done by the compiler.
 
Valentin Musoiu
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey!

I was formulating my 2nd explanation while Jim got to post twice.
It seems I am too slow of a writer!

Thanks, Jim!
Happy to help! Too bad I don't have a better explaining ability!
 
dasun sam
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hello Valentin Musoiu!!!

it seems this is issue on compile time and run time.is this kind of problems are not related to the scjp 6.0 syllabus?
 
Vinoth Kumar Kannan
Ranch Hand
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jim Hoglund wrote:Valentin's explanation above works for me. How about the rest of you?

Jim ... ...


Works for me too!
Thanks for your great explanation Valentin!
 
Ranch Hand
Posts: 623
1
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Great question guys and of course BIG thanks to Valentin for great explanation.

BTW guys - I love this forum already - it's only 2 days since I'm seriously reading it and it feels like almost every post is brining so much valuable knowledge! :-)
 
Valentin Musoiu
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

dasun sam wrote:hello Valentin Musoiu!!!

it seems this is issue on compile time and run time.is this kind of problems are not related to the scjp 6.0 syllabus?



Hey, Sam!

Indeed, I suppose this problem took us furter than the objectives. However, polymorphism is an important part of the exam. And to understand better polymorphism, it is better to, at least, read something about these compile time and runtime issues.

In fact, if I may (excessively) sum up, the whole idea is simple:
-the compiler does much of the work. He prepares everything for a "good run" of the program, making sure everything is alright. But he knows only the reference types he works with. So he deals with that, supposing all the objects have the same type as their references.
-only at runtime, to support polymorphism, it is possible to call other methods than those "prepared" by the compiler, based on the object types, if the methods were overriden (somewhere in the inheritance tree between reference and object type). But all the other details remain the same as they were "arranged" by the compiler.

I wouldn't know what is and is not actually required for the exam (I will take it in less than 3 weeks)... Hope there will not be a lot of questions this hard!!!
 
Vinoth Kumar Kannan
Ranch Hand
Posts: 276
Netbeans IDE Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So Valentin, having a method in a derived class with the same name as in the base class only with a different return type(ofcourse a covariant type) is called overloading/overriding?!
Overloading is completely resolved at compile time, but here it is partially at compile-time and partially at run-time...what do we call this?
 
Ranch Hand
Posts: 1051
Eclipse IDE Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This was a great explaination by Valentin
 
Jim Hoglund
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Overriding : This is when a behavior (method) in a parent class is replaced (or overridden) by
a modified behavior defined in a subclass. The overriding subclass method must have the same
name and call parameters as the parent method. It must also have a "compatible" return type;
the same as the parent method's return type, or any subclass of it. Think of the two methods as
having "almost the same" signature. (There are some rules about "compatible" exceptions too,
but let's save this for another day.)

Overloading : Think of these as very different methods that happen to share the same name.
They must have different parameter lists and may have any return type. For the compiler, they
could easily have different names. It's the software designer that wants to reuse the name, to
make the code more readable.

Jim ... ...
 
dasun sam
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks to everyone who giving their ideas here.can anyone explain this problem within scjp scope.i mean using priciples of polymorphism and overriding,covarient returns.
 
Jim Hoglund
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
All three concepts: overriding, overloading and covariant return types,
are fundamental Java concepts and, therefore, well within the scope
of the SCJP exams. So learn them well.

Jim ... ...
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic