如何在实现类中强制执行getFoo()方法,返回相同实现类的类型列表。
public interface Bar{
....
List<? extends Bar> getFoo();
}
现在,实现Bar的类返回实现Bar的任何类的对象。我想让它更严格,以便实现Bar的类在getFoo()中返回一个只有它的类型的对象列表。
答案 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方法。