当我有一个接口
public interface Foo<T> {
T someMethod();
}
有没有办法确保当某个类实现了该接口时,泛型类型与实现类相同。
例如:
public class Bar implements Foo<Bar> {
Bar someMethod() {
return new Bar();
}
}
public interface Recur<T extends Recur<T>> {
// ...
}
注意第二次提到的T
。这是CRTP的一个重要部分。
此外,这就是java.util.Enum
的定义方式,因此名为Foo
的枚举类型必须派生自Enum<Foo>
,因此在Java中也不是不常见的模式。
Recur<T>
解决方案和 tangens 提出的 Recur<?>
解决方案之间的区别。public interface Recur<T extends Recur<T>> {
T foo();
}
class A implements Recur<B> {
@Override
public B foo() {
return new B();
}
}
class B implements Recur<A> {
@Override
public A foo() {
return new A();
}
}
<T>
,上述代码将无法编译;使用<?>
,则可以。但这只是纠缠于细节,它并不改变 tangens 的中心观点,即在已有有效的Recur
实现的情况下,您可以使后续的实现使用已经有效的类型,而不是它本身。我仍然认为这值得一些价值,但这并不比 tangens 的答案更有价值。public interface Foo<T extends Foo<?> > {
T someMethod();
}
通过这样做,你可以确保someMethod()
返回一个实现了Foo
接口的对象。
编辑:
即使有这样一个接口定义:
public interface Foo<T extends Foo<T > > {
T someMethod();
}
Bar2
。public class Bar2 implements Foo<Bar2 > {
@Override
public Bar2 someMethod() {
return new Bar2();
}
}
然后您可以定义一个类Bar
来实现Foo
,但不返回Bar
而是返回Bar2
:
public class Bar implements Foo<Bar2 > {
@Override
public Bar2 someMethod() {
return new Bar2();
}
}
Bar
一样准备对抗接口的使用。Foo
接口的 Bar
类型只能实现 Foo<Bar>
,而不能实现 Foo<Object>
(例如)。这是可能的,并且可以使用 java.util.Enum
来实现。 - C. K. Young<?>
和 <T>
之间仍然存在差异,但这只是纠结细节,并没有实质性地改变答案的性质。 - C. K. Young这是不能完成的,因为涉及到类型擦除。
编辑:
我被踩了,这里再做一些解释:
public interface Foo<T>;
T
是在运行时可用的,因此它无法被检查。但是,可以自定义注释来强制执行此操作。
FancyStringList
而非ArrayList<FancyString>
,Color
而非Enum<Color>
? - Ray Jasson