• 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 returns and Casting

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

The below code is my version of a whizlabs mock question. I am not 100% sure of the solution that is given.

Line 1 compiles fine and gives the result "In Oval". This tells me that it has used the method in the Oval class.

Now its Line 2 which confuses me. The whizlabs solution says that c.getValue() must be cast to a String as an Object reference was used.

I assumed since String is a subclass of Object and that the Oval class method would be used, then the cast is not needed. I know my assumption is wrong as a cast is definitely needed (i complied the code).

So can any fellow rancher explain why the cast is needed as c.getValue() returns a String?

============================================================
class Circle{

Object getValue(){
return "In Circle";
}
}

class Oval extends Circle{

String getValue(){
return "In Oval";
}
}

public class CovariantTest {

public static void main(String[] args){

Circle c = new Oval();

System.out.println(c.getValue());//Line 1

String s = (String) c.getValue();//Line 2
System.out.println(s);//Line 3

}
}
 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
"System.out.println(c.getValue());//Line 1"
Here the cast is not needed, because object is returned and its method toString is called like everytime any object is printed.

"String s = (String) c.getValue();//Line 2"
Here the explicit cast is needed, because you are assigning Object to String variable. Object is-a String test is not true so you need ecplicit cast.

String test = "X";
Object o = test;
Other way around, if you are assigning String to Object variable, you don't need a cast because implicit cast can be used since String is-a Object test is true.
 
Ranch Hand
Posts: 664
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks..

I was wonderting too about the question but couldn't come up with answers.
 
Ranch Hand
Posts: 52
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Let's discuss for what happens in the line #2.

When invoking method or accessing variable from an instance, the compiler always looks at the reference variable.



Here, the compiler looks at the Circle, whose getValue()'s return type is Object. So in the line 2 you have to perform explicit cast.
 
Santiago Bravo
Ranch Hand
Posts: 226
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for your response guys. But I would like some further clarification if possible please.


If c.getValue() return type is an Object as the Circle reference has a getValue() return type Object, why does the Oval() class method get invoked?

When I compile and run the code from my first post I get:

In Oval
In Oval

So does that mean that the c reference of type Circle will look in the Circle Class if the method is there and the return type has to be of the same type? Then it goes to the Oval class as it is an Oval object being used so it will print "In Oval".

Am I on the right track?
 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
class Circle{

Object getValue(){
return "In Circle";
}
}

The above code is defining a class 'Circle'

class Oval extends Circle{

String getValue(){
return "In Oval";
}
}

The above piece of code is extending 'Circle' and 'overriding'(as there is no change in method arguments and the return is a subtype of Object so it is a legal override) the method getValue method.

======================================
public class CovariantTest {

public static void main(String[] args){
===========================================
Circle c = new Oval();

//at runtime c is recognized as an oval object so "In oval" is printed
System.out.println(c.getValue());//Line 1
//here the explicit cast is not needed
String s = (String) c.getValue();//Line 2
System.out.println(s);//Line 3

}
}
 
Bharath Raghavendra
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Small correction to the above solution .The explicit cast is needed as the object Circle publishes that it has a method 'getValue' that takes no argument and returns Object, so everyone who runs c.getValue() expects an object on 'c'.So eventhough c.getValue() is returning a String it is upcasting it to 'Object' . We have to downcast it before using .Hope that clarifies.
 
Santiago Bravo
Ranch Hand
Posts: 226
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks!

I understand now.
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic