Reputation: 22018
Consider this abstract class
abstract class AbstractBox {
abstract Object getContent();
}
Now my implementation of a StringBox
, but there might be other Box
es implementations that would return any type of content, preventing me from making the return type of the abstract method any more concrete:
class StringBox extends AbstractBox {
@Override
Object getContent() {
return "";
}
}
Instead of letting getContent()
declaring it will return an Object
where it is clear it will return a String
, I could also do
class StringBox extends AbstractBox {
@Override
String getContent() {
return "";
}
}
thus clearly stating what will be returned by getContent()
and still override the abstract method.
Upvotes: 1
Views: 409
Reputation: 131336
Overriding allow to specify a covariant return type and here you use it in the StringBox
subclass.
This feature is available since Java 1.5.
From the JLS.Chapter 8. Classes (emphasis is mine) :
8.4.5. Method Result
...
Return types may vary among methods that override each other if the return types are reference types. The notion of return-type-substitutability supports covariant returns, that is, the specialization of the return type to a subtype.
In practice if you manipulate variables with the StringBox
declared type, it has the benefit for the client of the class to return a more specific type, which is a good thing as it avoids downcasts.
For example :
StringBox box = new StringBox();
String boxContent = box.getContent();
But if you manipulate variables with the AbstractBox
declared type, it doesn't have any side effect at compile time or at runtime as the client expects still to have Object
as return type :
AbstractBox box = new StringBox();
Object boxContent = box.getContent();
In a general way using covariance return should be used if it makes the client code clearer and simpler (as without any cast).
Upvotes: 4
Reputation: 170723
Yes, it's "covariant return type".
The compiler still generates a "bridge method" returning Object
for StringBox
, so there is a very slight increase in code size (and potential decrease in performance, but that should be easily eliminated by JIT).
As @khelwood mentions, you quite often want to use generics instead of covariant return type (or in addition to it).
Upvotes: 2
Reputation: 7071
I do believe it's not a problem. If you use the abstract class for example if you have
AbstractBox box;
box.getContent()
you will get an object and you can cast if you know the implementation
If you use the concrete implementation you get the String (which is also an object).
Another solution to that would be to use a generics method for example:
abstract class AbstractBox<T> {
abstract T getContent();
}
and in the implementation add that as String
class StringBox extends AbstractBox<String> {
@Override
String getContent() {
return "";
}
}
I don't think it makes much difference though because you still have to use StringBox to know the implementaton
Upvotes: 0