What is a covariant return type in Java? In object-oriented programming in general?
Covariant return, means that when one overrides a method, the return type of the overriding method is allowed to be a subtype of the overridden method's return type.
To clarify this with an example, a common case is Object.clone() - which is declared to return a type of Object. You could override this in your own class as follows:
public class MyFoo
{
...
// Note covariant return here, method does not just return Object
public MyFoo clone()
{
// Implementation
}
}
The benefit here is that any method which holds an explicit reference to a MyFoo object will be able to invoke clone() and know (without casting) that the return value is an instance of MyFoo. Without covariant return types, the overridden method in MyFoo would have to be declared to return Object - and so calling code would have to explicitly downcast the result of the method call (even thought both sides "know" it can only ever be an instance of MyFoo).
Note that there's nothing special about clone() and that any overridden method can have a covariant return - I used it as an example here as it's a standard method where this is often useful.
Here is another simple example :
Animal class
public class Animal {
protected Food seekFood() {
return new Food();
}
}
Dog class
public class Dog extends Animal {
#Override
protected Food seekFood() {
return new DogFood();
}
}
It’s possible to modify the return type of the Dog’s seekFood() method to DogFood - a subclass of Food, as shown below:
#Override
protected DogFood seekFood() {
return new DogFood();
}
That’s perfectly a legal overriding, and the return type of Dog’s seekFood() method is known as covariant return type.
From the release of JDK 1.5, covariant types were introduced in Java. and I'll explain it to you with a simple case, : When we override a function the function is allowed to make changes to it's behaviour that's what you get to read in most of the books, but what they { authors } miss out on is that we can change the return type too.
check below link for clarification we can change the return type as long as it can be assigned to return type of Base version of the method.
So this feature of returning derived types is called COVARIANT...
Can overridden methods differ in return type?
covariant Return types simply means returning own Class reference or its child class reference.
class Parent {
//it contain data member and data method
}
class Child extends Parent {
//it contain data member and data method
//covariant return
public Parent methodName() {
return new Parent();
or
return Child();
}
}
To add to the above answers, overriding is possible among co-variant return types, with the constraint that the return type of the overriding method (subclass method) should be a subclass of the return type of the overridden method (superclass method). This is valid from Java 5 onwards.
Covariant return type specifies that the return type may vary in the same direction as the subclass
class One{
One get(){return this;}
}
class Two extends One{
Two get(){return this;}
void message(){
System.out.println("After Java5 welcome to covariant return type");
}
public static void main(String args[]){
new Two().get().message();
}
}
Before Java 5, it was not possible override any method
by changing the return type. But now, since Java5,
it is possible to override method by changing the return type
if subclass overrides any method
whose return type is Non-Primitive
but it changes its return type to subclass type.
It helps to avoid confusing type casts present in the class hierarchy
and thus making the code readable, usable and maintainable.
We get a liberty to have more specific return types when overriding
methods.
Help in preventing run-time ClassCastExceptions on returns
reference:
www.geeksforgeeks.org
The covariant return type in java, allows narrowing down return type
of the overridden method.
This feature will help to avoid down casting
on the client side. It allows programmer to program without the need
of type checking and down casting.
The covariant return type always
works only for non-primitive return types.
interface Interviewer {
default Object submitInterviewStatus() {
System.out.println("Interviewer:Accept");
return "Interviewer:Accept";
}
}
class Manager implements Interviewer {
#Override
public String submitInterviewStatus() {
System.out.println("Manager:Accept");
return "Manager:Accept";
}
}
class Project {
public static void main(String args[]) {
Interviewer interviewer = new Manager();
interviewer.submitInterviewStatus();
Manager mgr = new Manager();
mgr.submitInterviewStatus();
}
}
Other example is from Java,
UnaryOperator.java
#FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
/**
* Returns a unary operator that always returns its input argument.
*
* #param <T> the type of the input and output of the operator
* #return a unary operator that always returns its input argument
*/
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
Function.java
#FunctionalInterface
public interface Function<T, R> {
........
........
........
........
static <T> Function<T, T> identity() {
return t -> t;
}
}
Before Java5, it was not possible to override any method by changing the return type. But now, since Java5, it is possible to override method by changing the return type if subclass overrides any method whose return type is Non-Primitive but it changes its return type to subclass type.
Related
I have two interfaces :
interface S {
public String m1();
}
interface O {
public Object m1();
}
I decide to implement both O and S in a class Test :
class Test implements O, S {
}
My question :
Why must I only implement the method public String m1() and not the other ?
And secondly, why can't I implement public Object m1() instead of public String m1() ?
Java allows you to use covariant return types for overriding methods.
This means that an overriding method can return a subtype of the type declared on the overridden method.
In this case, String is covariant with Object; since all Strings are also Objects, it is a suitable return type for implementing O.m1() and O.m2().
But you can't have two methods with the same signature in a single class (return type isn't part of the signature). So you can only implement at most 1, when the return types are compatible, as here. (And if they are not compatible, you'd get a compiler error).
String is instance of Object Class. So when you are implementing interface method you can change type conversion. Only primitive type like int,double..and others are not able to type conversion.
you may use this
class Test implements O, S {
O _o = new O() {
#Override
public Object m1(){
return new Object();
}
};
#Override
public String m1(){
return "";
}
}
Test t = new Test();
t.m1();// m1 from s
t._o.m1();// m1 from O
I have a superclass with the method:
protected <E extends Enum<E>,T extends VO> void processarRelatorioComEstado(Date dataInicial, Date dataFinal, E estado) throws RelatorioException {
throw new UnsupportedOperationException("method not overridden");
}
and in one of its subclasses I want to do the following:
#Override
protected <E extends Enum<E>> DemonstrativoReceitaDespesasAnexo12Vo processarRelatorioComEstado(Date dataInicial, Date dataFinal, E estado) throws RelatorioException {
//do something
return DemonstrativoReceitaDespesasAnexo12Vo;
}
but this just doesn't work. The problem is that I have a reference to a superclass, and I want to call this method, but only in one of the subclasses.
According to java overridding
The overriding method has the same name, number and type of parameters, and return type as the method it overrides. An overriding method can also return a subtype of the type returned by the overridden method. This is called a covariant return type.
Here your method return type is different so it is not overridding.
You can't change the number of type parameters in the overridden method. As for your case, override clearly fails with the return type. But even if the return types were same, your method still wouldn't be override equivalent, as you have fewer type parameters in the supposed-to-be overridden method.
From JLS - Method Signature:
Two methods have the same signature if they have the same name and
argument types.
Two method or constructor declarations M and N have the same argument
types if all of the following conditions hold:
They have the same number of formal parameters (possibly zero)
They have the same number of type parameters (possibly zero)
So, even the following code would fail:
interface Demo {
public <S, T> void show();
}
class DemoImpl implements Demo {
#Override
public <T> void show() { } // Compiler error
}
As the method show() in class is not override equivalent with the method in interface, due to fewer type parameters.
So, you should make sure that the method signature is exactly the same, as specified in that JLS section (Same name, same number and type of parameters (including type parameters), co-variant return type).
Reading the comments above, I understand that the approach wouldn't work, so I make some changes in the code and work like a charm, follows the code:
superclass:
protected VO processarRelatorioComEstado(Date dataInicial, Date dataFinal, Enum<?> estado) throws RelatorioException {
throw new UnsupportedOperationException("method not overridden");
}
and the subclass:
public VO processarRelatorioComEstado(Date dataInicial, Date dataFinal, Enum<?> estado) throws RelatorioException {
//do something
return VOsubtype;
}
thanks guys.
Can overridden methods have different return types?
Java supports* covariant return types for overridden methods. This means an overridden method may have a more specific return type. That is, as long as the new return type is assignable to the return type of the method you are overriding, it's allowed.
For example:
class ShapeBuilder {
...
public Shape build() {
....
}
class CircleBuilder extends ShapeBuilder{
...
#Override
public Circle build() {
....
}
This is specified in section 8.4.5 of the Java Language Specification:
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.
A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2, if and only if the following conditions hold:
If R1 is void then R2 is void.
If R1 is a primitive type, then R2 is identical to R1.
If R1 is a reference type then:
R1 is either a subtype of R2 or R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9), or
R1 = |R2|
("|R2|" refers to the erasure of R2, as defined in §4.6 of the JLS.)
* Prior to Java 5, Java had invariant return types, which meant the return type of a method override needed to exactly match the method being overridden.
Yes it may differ but there are some limitations.
Before Java 5.0, when you override a method, both parameters and return type must match exactly. Java 5.0 it introduces a new facility called covariant return type. You can override a method with the same signature but return a subclass of the object returned.
In another words, a method in a subclass can return an object whose type is a subclass of the type returned by the method with the same signature in the superclass.
Yes, if they return a subtype. Here's an example:
package com.sandbox;
public class Sandbox {
private static class Parent {
public ParentReturnType run() {
return new ParentReturnType();
}
}
private static class ParentReturnType {
}
private static class Child extends Parent {
#Override
public ChildReturnType run() {
return new ChildReturnType();
}
}
private static class ChildReturnType extends ParentReturnType {
}
}
This code compiles and runs.
Broadly speaking yes return type of overriding method can be different. But it's not straight forward as there are some cases involved in this.
Case 1: If the return type is a primitive data type or void.
Output: If the return type is void or primitive then the data type of parent class method and overriding method should be the same.
e.g. if the return type is int, float, string then it should be same
Case 2: If the return type is derived data type:
Output: If the return type of the parent class method is derived type then the return type of the overriding method is the same derived data type of subclass to the derived data type.
e.g. Suppose I have a class A, B is a subclass to A, C is a subclass to B and D is a subclass to C; then if the super class is returning type A then the overriding method in subclass can return either A, or B/C/D type i.e. its sub types. This is also called as covariance.
yes It is possible.. returns type can be different only if parent class method return type is
a super type of child class method return type..
means
class ParentClass {
public Circle() method1() {
return new Cirlce();
}
}
class ChildClass extends ParentClass {
public Square method1() {
return new Square();
}
}
Class Circle {
}
class Square extends Circle {
}
If this is the then different return type can be allowed...
The other answers are all correct, but surprisingly all leaving out the theoretical aspect here: return types can be different, but they can only restrict the type used in the super class because of the Liskov Substitution Principle.
It is super simple: when you have "client" code that calls some method:
int foo = someBar.bar();
then the above has to work (and return something that is an int no matter which implementation of bar() is invoked).
Meaning: if there is a Bar subclass that overrides bar() then you still have to return something that doesn't break "caller code".
In other words: assume that the base bar() is supposed to return int. Then a subclass could return short - but not long because callers will be fine dealing with a short value, but not a long!
well, the answer is yes... AND NO.
depends on the question. everybody here answered regarding Java >= 5, and some mentioned that Java < 5 does not feature covariant return types.
actually, the Java language spec >= 5 supports it, but the Java runtime does not. in particular, the JVM was not updated to support covariant return types.
in what was seen then as a "clever" move but ended up being one of the worst design decisions in Java's history, Java 5 implemented a bunch of new language features without modifying the JVM or the classfile spec at all. instead all features were implemented with trickery in javac: the compiler generates/uses plain classes for nested/inner classes, type erasure and casts for generics, synthetic accessors for nested/inner class private "friendship", synthetic instance fields for outer 'this' pointers, synthetic static fields for '.class' literals, etc, etc.
and covariant return types is yet more syntactic sugar added by javac.
for example, when compiling this:
class Base {
Object get() { return null; }
}
class Derived extends Base {
#Override
#SomeAnnotation
Integer get() { return null; }
}
javac will output two get methods in the Derived class:
Integer Integer:Derived:get() { return null; }
synthetic bridge Object Object:Derived:get() { return Integer:Derived:get(); }
the generated bridge method (marked synthetic and bridge in bytecode) is what actually overrides Object:Base:get() because, to the JVM, methods with different return types are completely independent and cannot override each other. to provide the expected behavior, the bridge simply calls your "real" method. in the example above, javac will annotate both bridge and real methods in Derived with #SomeAnnotation.
note that you cannot hand-code this solution in Java < 5, because bridge and real methods only differ in return type and thus they cannot coexist in a Java program. but in the JVM world, method return types are part of the method signature (just like their arguments) and so the two methods named the same and taking the same arguments are nonetheless seen as completely independent by the JVM due to their differing return types, and can coexist.
(BTW, the types of fields are similarly part of the field signature in bytecode, so it is legal to have several fields of different types but named the same within a single bytecode class.)
so to answer your question fully: the JVM does not support covariant return types, but javac >= 5 fakes it at compile time with a coating of sweet syntactic sugar.
The return type must be the same as, or a subtype of, the return type declared
in the original overridden method in the superclass.
Overriding and Return Types, and Covariant Returns the subclass must define a method that matches the inherited version exactly. Or, as of Java 5, you're allowed to change the return type in the sample code
class Alpha {
Alpha doStuff(char c) {
return new Alpha();
}
}
class Beta extends Alpha {
Beta doStuff(char c) { // legal override in Java 1.5
return new Beta();
}
} } As of Java 5, this code will compile. If you were to attempt to compile this code with a 1.4 compiler will say attempting to use incompatible return type – sandeep1987 1 min ago
class Phone {
public Phone getMsg() {
System.out.println("phone...");
return new Phone();
}
}
class Samsung extends Phone{
#Override
public Samsung getMsg() {
System.out.println("samsung...");
return new Samsung();
}
public static void main(String[] args) {
Phone p=new Samsung();
p.getMsg();
}
}
YES it can be possible
class base {
base show(){
System.out.println("base class");
return new base();
}
}
class sub extends base{
sub show(){
System.out.println("sub class");
return new sub();
}
}
class inheritance{
public static void main(String []args) {
sub obj=new sub();
obj.show();
}
}
Yes. It is possible for overridden methods to have different return type .
But the limitations are that the overridden method must have a return type that is more specific type of the return type of the actual method.
All the answers have given examples of the overridden method to have a return type which is a subclass of the return type of the actual method.
For example :
public class Foo{
//method which returns Foo
Foo getFoo(){
//your code
}
}
public class subFoo extends Foo{
//Overridden method which returns subclass of Foo
#Override
subFoo getFoo(){
//your code
}
}
But this is not only limited to subclass.Even classes that implement an interface are a specific type of the interface and thus can be a return type where the interface is expected.
For example :
public interface Foo{
//method which returns Foo
Foo getFoo();
}
public class Fizz implements Foo{
//Overridden method which returns Fizz(as it implements Foo)
#Override
Fizz getFoo(){
//your code
}
}
import java.util.*;
class A extends HashSet<Integer> {
public boolean add(Object obj){ //compiler error
return true;
}
}
or
class Abc <T> {
public void add(T t){} //compiler error
public void add(Object i){} //compiler error (can't overload?)
}
Error:Name clash: The method add(Object) of type test2 has the same erasure as add(E) of type HashSet but does not override it
i do not know what is the concept behind above error can any one suggest where i can study this concept?
The concept at work here is called type erasure. HashSet defines a method add(T), and you define a method add(Object). At a glance one might think this is OK; that your method just overloads add. However, the erasure of T is Object and so the two have the same erased signature.
Now, that would be fine if your method properly overrode the method from HashSet. But to do so you should be using add(Integer) and not add(Object). You're not properly overriding the parent method, so instead it is reported as a conflict since a class cannot provide two methods with the same signature.
Your Abc example follows the same reasoning. The two methods you declared have the same erased signature so they clash.
Further Reading
Angelika Langer Generics FAQ
When does a method override its supertype's method?
Can a method of a non-generic subtype override a method of a generic supertype?
interface CollectionConverter<U> {
<T> List<T> toList(Collection<T> c);
void fooMethod(Class<?> c);
<E>Comparable<E> method3(E e);
Comparable<U> method4(U u);
}
class Overrider implements CollectionConverter<Integer> {
#Override
public List toList(Collection c) {
return null;
}
#Override
public void fooMethod(Class c) {
}
#Override
public Comparable method3(Object o) {
return null;
}
#Override
public Comparable method4(Integer u) {
return null;
}
}
This code works well.
In JLS: The notion of subsignature is designed to express a relationship between two methods whose signatures are not identical, but in which one may override the other. Specifically, it allows a method whose signature does not use generic types to override any generified version of that method. This is important so that library designers may freely generify methods independently of clients that define subclasses or subinterfaces of the library.
Did you try using Integer instead of Object obj i.e
public boolean add(Integer i)
{ //compiler error
return true;
}
The problem is that when you are extending Hashset , you are extending Integer Hashset and not the generic form. So, in the subclass your add method has to comply with the signature of the superclass method which is
public boolean add(Integer i) { }
If you want to extend from a totally generic Hashset implementation, try extending with
public class MyHashset extends Hashset<?> {
}
Then your add method should work with Object.
What is a covariant return type in Java? In object-oriented programming in general?
Covariant return, means that when one overrides a method, the return type of the overriding method is allowed to be a subtype of the overridden method's return type.
To clarify this with an example, a common case is Object.clone() - which is declared to return a type of Object. You could override this in your own class as follows:
public class MyFoo
{
...
// Note covariant return here, method does not just return Object
public MyFoo clone()
{
// Implementation
}
}
The benefit here is that any method which holds an explicit reference to a MyFoo object will be able to invoke clone() and know (without casting) that the return value is an instance of MyFoo. Without covariant return types, the overridden method in MyFoo would have to be declared to return Object - and so calling code would have to explicitly downcast the result of the method call (even thought both sides "know" it can only ever be an instance of MyFoo).
Note that there's nothing special about clone() and that any overridden method can have a covariant return - I used it as an example here as it's a standard method where this is often useful.
Here is another simple example :
Animal class
public class Animal {
protected Food seekFood() {
return new Food();
}
}
Dog class
public class Dog extends Animal {
#Override
protected Food seekFood() {
return new DogFood();
}
}
It’s possible to modify the return type of the Dog’s seekFood() method to DogFood - a subclass of Food, as shown below:
#Override
protected DogFood seekFood() {
return new DogFood();
}
That’s perfectly a legal overriding, and the return type of Dog’s seekFood() method is known as covariant return type.
From the release of JDK 1.5, covariant types were introduced in Java. and I'll explain it to you with a simple case, : When we override a function the function is allowed to make changes to it's behaviour that's what you get to read in most of the books, but what they { authors } miss out on is that we can change the return type too.
check below link for clarification we can change the return type as long as it can be assigned to return type of Base version of the method.
So this feature of returning derived types is called COVARIANT...
Can overridden methods differ in return type?
covariant Return types simply means returning own Class reference or its child class reference.
class Parent {
//it contain data member and data method
}
class Child extends Parent {
//it contain data member and data method
//covariant return
public Parent methodName() {
return new Parent();
or
return Child();
}
}
To add to the above answers, overriding is possible among co-variant return types, with the constraint that the return type of the overriding method (subclass method) should be a subclass of the return type of the overridden method (superclass method). This is valid from Java 5 onwards.
Covariant return type specifies that the return type may vary in the same direction as the subclass
class One{
One get(){return this;}
}
class Two extends One{
Two get(){return this;}
void message(){
System.out.println("After Java5 welcome to covariant return type");
}
public static void main(String args[]){
new Two().get().message();
}
}
Before Java 5, it was not possible override any method
by changing the return type. But now, since Java5,
it is possible to override method by changing the return type
if subclass overrides any method
whose return type is Non-Primitive
but it changes its return type to subclass type.
It helps to avoid confusing type casts present in the class hierarchy
and thus making the code readable, usable and maintainable.
We get a liberty to have more specific return types when overriding
methods.
Help in preventing run-time ClassCastExceptions on returns
reference:
www.geeksforgeeks.org
The covariant return type in java, allows narrowing down return type
of the overridden method.
This feature will help to avoid down casting
on the client side. It allows programmer to program without the need
of type checking and down casting.
The covariant return type always
works only for non-primitive return types.
interface Interviewer {
default Object submitInterviewStatus() {
System.out.println("Interviewer:Accept");
return "Interviewer:Accept";
}
}
class Manager implements Interviewer {
#Override
public String submitInterviewStatus() {
System.out.println("Manager:Accept");
return "Manager:Accept";
}
}
class Project {
public static void main(String args[]) {
Interviewer interviewer = new Manager();
interviewer.submitInterviewStatus();
Manager mgr = new Manager();
mgr.submitInterviewStatus();
}
}
Other example is from Java,
UnaryOperator.java
#FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
/**
* Returns a unary operator that always returns its input argument.
*
* #param <T> the type of the input and output of the operator
* #return a unary operator that always returns its input argument
*/
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
Function.java
#FunctionalInterface
public interface Function<T, R> {
........
........
........
........
static <T> Function<T, T> identity() {
return t -> t;
}
}
Before Java5, it was not possible to override any method by changing the return type. But now, since Java5, it is possible to override method by changing the return type if subclass overrides any method whose return type is Non-Primitive but it changes its return type to subclass type.