Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have an interface method defined with a generic return type and a concrete implementation define the return type?

Tags:

I have would like to create an interface:

public interface OperandValue {     <T> T getValue(); } 

I would then like to have a concrete implementation like this:

public class NumberOperandValue implements OperandValue {     @Override     public <Integer> Integer getValue()     {         // some integer value that is set elsewhere         return 1;     } } 

Eclipse is underlining the <Integer> giving me a warning that says:

The type parameter Integer is hiding the type Integer

I appreciate any suggestions on if this can work somehow. I realize that I could define the generic type at the interface level and not the method level, but would like to try to get this to work if possible.

like image 669
Steve Avatar asked Sep 15 '11 15:09

Steve


People also ask

Can a method have return type as interface?

If an interface is defined to be the return type of a method then instances of classes derived from that interface can be returned. The benefit of doing that is no different from returning objects of classes derived from a class.

Can we have interface as return type in java?

Generic Interfaces This interface represents an interface which contains a single method called produce() which can produce a single object. Since the return value of produce() is Object , it can return any Java object.

Can a generic implement an interface?

Only generic classes can implement generic interfaces. Normal classes can't implement generic interfaces.

Can an interface have defined methods?

Like a class, an interface can have methods and variables, but the methods declared in an interface are by default abstract (only method signature, no body). Interfaces specify what a class must do and not how.


1 Answers

You probably want to change the interface to:

public interface OperandValue<T> {     T getValue(); } 

And the implementation to:

public class NumberOperandValue implements OperandValue<Integer> {     @Override     public Integer getValue()     {         // some integer value that is set elsewhere         return 1;     } } 

Now you're telling the interface what type you want that method to return. In other words, you're making the interface type generic, rather than the method declaration. But that seems to be what you want.

As a side note:

public <Integer> Integer getValue() 

Actually means, 'define a generic type parameter with the name "Integer"' where getValue returns the "Integer" type that you just defined.

Responding To Steve's Comments Below:

when I remove the <Integer> from my method implementation that I then get a warning that says: Type safety: The return type Integer for getValue() from the type NumberOperandValue needs unchecked conversion to conform to T from the type OperandValue

That warning message indicates that you're breaking the rules when using Java generics. To see why, let's consider what the method signature means before you remove the <Integer> type parameter.

public <Integer> Integer getValue() 

This signature means that the method getValue returns a value of type Integer where Integer is defined as the generic type parameter you defined between the angle brackets. The meaning of the string Integer is completely arbitrary and would have exactly the same meaning as:

public <T> T getValue() 

For clarity, let's stick with this version of your method signature for the purposes of your question. What happens when we remove the type parameter?

public T getValue() 

Now if you were to try to compile, you'd get an error that T is undefined. However, because your original type signature declared the type parameter with the name Integer, when you removed it, you were left with:

public Integer getValue() 

Because Integer is already a predefined type, the method signature is still technically legal. However, it is only an accident that the name of your type parameter happens to be the same as a type that already exists.

Furthermore, because your interface already declared a method signature with generics, the Java compiler generates a warning when you remove it from the implementation. Specifically, the compiler is concerned that in the base class, the return type of the method is the (type-erased to Object) generic parameter named Integer, which is not the same type (nor is it known to be type compatible with) the system class named Integer (or java.lang.Integer to be precise).

like image 165
Kirk Woll Avatar answered Sep 22 '22 19:09

Kirk Woll