Different return types of abstract method in java without casting

I am trying to implement and override a method with different return types without being forced to use the return type.

public abstract class A { public abstract Object getValue(String content); } public class B extends A { public String getValue(String content) {...} } public class C extends A { public int getValue(String content) {...} } public class D extends A { public boolean getValue(String content) {...} } // Main loop: for (A a : allAs) { // I want to use the method getValue() and corresponding to the type return a String, int or boolean without casting the return type } 

My question is: Is it possible to return different types without being forced to throw? What does an abstract method look like to solve a problem?

I think there should be a solution, because the compiler should know the return type ...

+6
source share
4 answers

In your example, classes C and D will not compile. Overridden methods in them violate the Liskov substitution principle, since their return type is incompatible with their parent class. What you want to do can be done using generics if you are willing to refuse to use primitives as the return type.

 abstract class A<T> { public abstract T getValue(String content); } class B extends A<String> { public String getValue(String content) { } } class C extends A<Integer> { public Integer getValue(String content) { } } class D extends A<Boolean> { public Boolean getValue(String content) { } } 
+13
source

What you described is generally impossible. However, if a subclass returns a "narrower" subtype of the return method of the superclass, this is called a "covariant return type" and is allowed in Java with JDK 1.5. However, based on your example, I don't think covariant return is what you are looking for.

I guess you want

 for (A a : allAs) { String b = a.getValue(); int c = a.getValue(); } 

The problem here, of course, is that the compiler does not know at compile time which of these two statements is correct, and they cannot be true.

+3
source

You can use generics.

 public abstract class A<T> { public abstract T getValue(String content); } public class B extends A<String> { public String getValue(String content) {...} } 

etc ... int does not work as a return type for this, but Integer will.

I do not print on the compiler, so there may be typos ...

As Jim and Chris pointed out, if you iterate over As, you can get the result "A", which is Object.

+2
source

In your example, the definition of class B is fine, since String is a subclass of Object . The other two will not compile, as they are primitive types. You can replace them with Integer and Boolean to return this solution.

As for your main loop, if you repeat them as references to A , you can only use the A definition of the method that Object returns.

0
source

All Articles