为实现接口的类强制执行返回类型

时间:2011-12-06 22:35:57

标签: java generics

如何在实现类中强制执行getFoo()方法,返回相同实现类的类型列表。

public interface Bar{
     ....
     List<? extends Bar> getFoo(); 
}

现在,实现Bar的类返回实现Bar的任何类的对象。我想让它更严格,以便实现Bar的类在getFoo()中返回一个只有它的类型的对象列表。

7 个答案:

答案 0 :(得分:17)

不幸的是,Java的类型系统无法强制执行。

但是,通过使用:

,你可以非常接近
public interface Bar<T extends Bar<T>> {
    List<T> getFoo();
}

然后你的实现类可以这样实现它:

public class SomeSpecificBar implements Bar<SomeSpecificBar> {
    // Compiler will enforce the type here
    @Override
    public List<SomeSpecificBar> getFoo() {
        // ...
    }
}

但没有什么能阻止另一个班级做这件事:

public class EvilBar implements Bar<SomeSpecificBar> {
    // The compiler's perfectly OK with this
    @Override
    public List<SomeSpecificBar> getFoo() {
        // ...
    }
}

答案 1 :(得分:2)

这在Java中是不可能的,但您可能想知道在界面中强制执行此操作的用例是什么。

  • 如果你针对接口进行编程(通常你会这样做,为什么还要定义接口),这个类型就不知道了
  • 如果针对特定类进行编程,则此线程已经提供了有关如何实现该特定类以返回List<itself>的选项。并且由于您针对该特定类进行编程,因此编译器可以访问该特定的返回类型并了解它

答案 2 :(得分:2)

这里的interface Bar<T extends Bar<T>>答案是正确的,但我只是想补充一点,如果这是你想要强制执行的东西,你可能想要看看编写你的对象而不是使用继承。在不太了解您的课程的情况下,可能看起来像这样:

public interface FooGetter<T> {
    List<? extends T> getFoo();
}

public class FooComposer<T extends Bar> {
    ...
    final T bar;
    final FooGetter<T> barGetter;
}

或者它可能看起来非常不同......但重点是,如果你想让两个Ts匹配,那么组合可能就是答案。

当然,即使这样也可以使用原始类型来规避......但是,如果有人这样做,他们只是使用原始List,当他们获得ClassCastExceptions时,你可以安全地击中它们。 :)

答案 3 :(得分:1)

您应该在Bar上推断通用:

public interface Bar<T extends Foo> {
  ...
  List<T> getFoo();
}

您可以参数化该方法,但这不能确保返回类型与该类的匹配。

答案 4 :(得分:0)

也许是这样的

public interface Bar {
     ....
     List<? extends Bar> getFoo(); 
}

public class T implements Bar {
     List<T> getFoo();
}

public class TestClass extends T {};

答案 5 :(得分:0)

我最喜欢yshavit回答,但我无法理解代码。 所以我会尝试编写我认为应该的代码。

interface Bar
{
    // stuff
    // don't bother with the getFoo method
}

interface BarUtils
{
    < T extends Bar > List < ? extends T > getFoo ( T bar ) ;
}

答案 6 :(得分:0)

这个怎么样:

interface Bar
{
    // everything but getFoo ( ) ;
}

interface FooGetter < T >
{
    List < ? extends T > getFoo ( ) ;
}

interface BarRef < T extends Bar & FooGetter < T > >
{
    T get ( ) ;
}

任何实现BarRef的东西都必须实现T,任何实现T的东西都必须具有适当强制执行的getFoo方法。