Method return type to fulfill multiple interfaces

后端 未结 4 912
野性不改
野性不改 2021-02-05 08:30

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         


        
相关标签:
4条回答
  • 2021-02-05 08:38

    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.

    0 讨论(0)
  • 2021-02-05 08:44

    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.

    0 讨论(0)
  • 2021-02-05 08:45

    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;
    } 
    
    0 讨论(0)
  • 2021-02-05 09:01
    interface FooBar extends Foo, Bar {
        FooBar getFooBar();
    }
    
    0 讨论(0)
提交回复
热议问题