Is it possible to specify a method which returns a object that implements two or multiple interfaces?
Say we have the following interfaces:
interface Foo
Another solution would be to define a new interface that extends Foo and Bar and to use that as return type.
I would say go for this option.
You can make T a class parameter:
class SomeImplementor<T extends Foo & Bar> implements FooBar {
private T fSomeField;
public T getFooBar() {
return fSomeField;
}
}
As to why your generics approach didn't work. Lets create the following two classes that implement Foo
and Bar
:
class A implements Bar, Foo{
private int a;
...
}
class B implements Bar, Foo{
private String b;
...
}
class SomeImplementor implements FooBar {
private A someField;
public <T extends Foo & Bar> T getFooBar() {
return someField;
}
}
So we should now be able to execute the following:
SomeImplementor s = new SomeImplementor();
A a = s.getFooBar();
B b = s.getFooBar();
Although getFooBar()
returns an object of type A, which has no valid cast to type B (where will the String
member come from?), even though B fulfills the requirement of <T extends Foo & Bar>
, i.e. is a valid T
.
In short, the compiler (remember, generics is a compile-time mechanism) can't guarantee that every T
of type <T extends Foo & Bar>
can have an assignment to it of type A
. Which is exactly the error you see - the compiler can't convert the given A to every valid T.
You could return a container to provide Foo and Bar.
public class Container{
private FooBarBam foobar;
public Bar asBar(){
return foobar;
}
public Foo asFoo(){
return foobar;
}
}
This way your code would not have to implement a third interface. Downside is that it is an additional layer of indirection.
As for why the generic approach does not work: there is no way to provide the type of T and the compiler can't just guess its type, so resolving T is not possible.
davin's answer looks good but also requires a public class/interface which implements Foo and Bar to work.
Update:
The problem is that the compiler does not know that the type of T should be FooAndBarImpl, it would have to guess and a guessing compiler leads to bad and unpredictable code.
Even a hack using Lists wont compile since the & operator is not supported. While it should be possible to implement it looks like generics currently don't support multiple bounds within return types.
//Does not compile expecting > after Foo
List<? extends Foo & Bar> getFooBar(){
final List<FooAndBarImpl> l = new ArrayList<FooAndBarImpl>();
l.add(new FooAndBarImpl());
return l;
}
interface FooBar extends Foo, Bar {
FooBar getFooBar();
}