erwingun2010
erwingun2010

Reputation: 123

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 cast 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 it possible to return different types without being forced to cast? How has the abstract method look like to solve the problem?

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

Upvotes: 9

Views: 28069

Answers (4)

user949300
user949300

Reputation: 15729

You could 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 doesn't work as a return type for this, but Integer would.

I'm not typing at a compiler so there may be typos...

As noted by Jim and Chris, if you are looping over As, you can only get the "A" result, which is Object.

Upvotes: 2

Perception
Perception

Reputation: 80603

In your example, classes C and D will not compile. The overridden methods in them violate the Liskov substitution principle, aka, their return type is incompatible with their parent class. What you are looking to do can be accomplished with generics, as long as you are willing to forego the use of primitives as your 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) { }
}

Upvotes: 19

Krease
Krease

Reputation: 16215

In your example, the definition of class B is ok, since String is a subclass of Object. The other two wont compile, since they are primitive types. You could replace them with Integer and Boolean returns to resolve that though.

As for your main loop, if you're iterating over them as references to A, you'll only be able to use A's definition of the method, which returns Object.

Upvotes: 1

Jim Garrison
Jim Garrison

Reputation: 86764

What you describe is not possible in general. However, if the subclass returns a "narrower" subtype of the superclass method return, this is called a "covariant return type" and is allowed in Java since JDK 1.5. However, based on your example I do not think covariant return is what you are looking for.

I assume what you want is

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

The problem here is, of course, that the compiler has no way of knowing at compile time which of those two statements is correct, and they can't both be correct.

Upvotes: 3

Related Questions