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.
Related
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.
I've made my code as generic as possible to try and help people in the future. My abstract class has a method of the type class and and an input of the type class. In the class that extends the abstract, I try to implement that method to no avail. What am I doing wrong?
public abstract class A {
public abstract A method1(A arg);
}
public class B extends A {
#Override
public B method1(B arg) { "...insert code here"} // Error: The method method1(B) must override or implement a supertype method
}
To achieve what you want : associating the type of the argument to the declared class, you could use generics.
abstract class :
public abstract class A <T extends A<T>> {
public abstract T method1(T arg);
}
concrete class :
public class B extends A<B> {
#Override
public B method1(B arg) {
...
return ...
}
}
Think about the Liskov substitution principle: in order to be indistinguishable from a superclass, the subclass must accept all of the same parameters that the superclass would; and return something that the superclass might.
Another way to put this is that the subclass method can:
Return a more specific type that the superclass method (since this is a value that the superclass might return); for example, if the superclass returns Object, the subclass can return a String, because all Strings are Objects.
This is called a covariant return type, and is permitted in Java. Subclasses can not only return more specific return types, they can also throw more specific checked exceptions than the superclass; but they can also not declare that they throw the checked exceptions thrown by the superclass method.
Accept a more general type than the superclass method (since this allows the subclass to accept all parameters that the superclass would).
This would be called a contravariant parameter type; but it is not permitted in Java. The reason is to do with the way that overloads are selected in Java: unfortunately, the method signatures (which includes the parameter types, but not the return type) have to be identical.
The relevant section of the language spec is JLS Sec 8.4.8.3.
Your problem is making the parameter type B: this is more specific than A, so an instance of B is not substitutable for an instance of A, because A.method1 accepts a parameter A, whereas B.method1 does not.
Make B.method1 take a parameter of type A.
The type and no of parameter should remain. The return type, if it is of primitive type, should remain same, but if it is of reference type then it can be of subclass type.
In your case change this public B method1(B arg) { "...insert code here"} to public B method1(A arg) { "...insert code here"}
Every thing you have written is right except overidden method argument type,you can't change the signature of superclass abstract method while overiding in subclass.
public abstract class A {
public abstract A method1(A arg);
}
public class B extends A {
#Override
public B method1(A arg) { "...insert code here"} // Error: The method method1(B) must override or implement a supertype method
}
The contract of A.method1 means that every object that is an A must have a method1 which can take any A object.
In the case of B.method1, it can take a B object, but it cannot take another A.
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.
Does anyone know the definitive answer to why the following isn't allowed by the java compiler?
class BaseClass {
public <T extends Number> T getNumber(){
return null;
}
}
class SubClass extends BaseClass{
#Override
public <T extends Integer> T getNumber(){
return null;
}
}
this causes the compiler to complain with:
"The method getNumber() of type SubClass must override a superclass method"
Now, when I put this to my colleagues some have tried to explain that it will cause confusion with the compiler. However, as was also pointed out the following, which is conceptually similar, is compilable.
class BaseClass<T extends Number> {
public T getNumber(){
return null;
}
}
class SubClass<T extends Integer> extends BaseClass<T>{
#Override
public T getNumber(){
return null;
}
}
This can be abused if the subclass calls the super implementation, but the compiler provides a warning to this effect. My only conclusion is that this is a compiler oversight on the part of folks at Sun (can't bring myself to say Oracle :-S).
Anyone have the definitive answer to this one?
Suppose it would indeed be allowed to add more restrictions to the type parameter on a derived class.
Then what if your class also had a <T extends Number> void setNumber(T number) method?
BaseClass foo = new SubClass();
long longValue = 42;
foo.<Long>setNumber(longValue);
The above would be accepted by the compiler because BaseClass.setNumber accepts any type parameter derived from Number. But the actual instance only accepts integers!
You could argue that if the type parameter is only used for the return value, it should automatically be considered covariant. But then the compiler would have to make sure that you don't use the type parameter inside the method body in a non-covariant way.
(In C# 4.0 this was actually solved, but it involves explicitly marking your type parameters as covariant or contravariant with the out and in keywords. It was not something that could simply be allowed by the compiler without changing the language.)
Because there is no covariance here. Covariance means 'varies with', and it refers to the return type varying as the containing class type. That's not happening here. There is no 'co' in your covariance.
#Wim Coenen provided a good answer.
Here is a small clarification.
If this would compile, what would you expect happened:
import java.math.BigInteger;
class BaseClass {
public <T extends Number> T getNumber(T n) {
System.out.println("Int value: " + n.intValue());
return n;
}
}
class SubClass extends BaseClass {
#Override
public <T extends BigInteger> T getNumber(T n) {
System.out.println("Int value: " + n.intValue());
// BigInteger specific!
System.out.println("Bit count: " + n.bitCount());
return n;
}
}
public class Main {
public static void main(String[] args) {
BaseClass sub = new SubClass();
// sub looks like a BaseClass...
// ...but since it's a SubClass it expects a BigInteger!
sub.getNumber(new Integer(5));
}
}
I don't quite follow your issue:
When I implemented your first portion of source code and compiled using javac *.java, it compiled fine. However, if I changed your SubClass.getNumber() method to do this...
/* (non-Javadoc)
* #see constraint.base.BaseClass#getNumber()
*/
#Override
public <T extends Number> T getNumber() {
// TODO Auto-generated method stub
return super.getNumber();
}
I get the following error:
SubClass.java:18: type parameters of <T>T cannot be determined; no unique maximal instance exists for type variable T with upper bounds T,java.lang.Number
return super.getNumber();
^
1 error
The reason for the code above is that by calling super.getNumber(), the compiler doesn't have any input that infer type T hence it cannot determine what T will be returned by super.getNumber() and, thus it can't satisfy the return type with SubClass.getNumber()
Now, in order to have obtained the error from the compiler, "The method getNumber() of type SubClass must override a superclass method", your BaseClass should have been abstract along with it's getNumber() method.
As for the 2nd piece of code you've provided, the subclass can, in effect, call super.getNumber() as the compiler will know (on compiling) that the SubClass's Generic Parameter Type is inferred to the Parameter Type of BaseClass.
Besides that, I really didn't know what you were trying to ask.
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.