【发布时间】:2012-11-30 01:54:52
【问题描述】:
假设我有这个界面:
interface Foo<T extends Foo<T>> { // ... }
以及以下三个实现它的类:
class TrueFoo implements Foo<TrueFoo > { // ... }
class FalseFoo implements Foo<FalseFoo> { // ... }
class WrongFoo implements Foo<FalseFoo> { // ... }
// ^^^^^^^^ this here is wrong, only
// Foo<WrongFoo> should be allowed
以下方法的方法签名需要什么来强制我可以返回 TrueFoo 或 FalseFoo 类型的对象,但不能返回 WrongFoo...
public ???? getFoo(boolean which) {
return which ? new TrueFoo() : new FalseFoo();
}
以下不起作用:
-
这让我也可以返回一个新的 WrongFoo():
public Foo<?> getFoo(boolean which) { return which ? new TrueFoo() : new FalseFoo(); } -
这不允许我返回任何东西(解释如下):
public <FooType extends Foo<FooType>> FooType getFoo(boolean which) { return which ? new TrueFoo() : new FalseFoo(); }问题在于 FooType 的类型是由我调用函数
getFoo()的上下文决定的,而不是由我实际尝试返回的对象决定的。
顺便说一下,调用方法时强制执行此签名很容易:
public <FooType extends Foo<FooType>> void test(FooType foo) {
// Do something with foo
}
如果您尝试使用 WrongFoo 的实例调用它,这将给您一个绑定不匹配错误。
让我觉得应该有一种方法可以对方法返回类型执行此操作。
或者有没有办法在 Foo 的接口定义中强制执行此签名?
编辑:
为了帮助可视化这个界面应该做什么,例如,您可以考虑这个版本:
interface CanCopy<Type extends CanCopy<Type>> {
public Type copy();
}
显然像Foo implements CanCopy<Bar> 这样的类没有任何意义,只有Foo implements CanCopy<Foo> 或Bar implements CanCopy<Bar>。
编辑 2:
正如存在解决方案的概念验证一样,我可以为自己定义以下帮助器类:
class FooResult {
private final Foo<?> foo;
public <FooType extends Foo<FooType>> FooResult(FooType foo) {
this.foo = foo;
}
@SuppressWarnings("unchecked")
public <FooType extends Foo<FooType>> FooType getFoo() {
return (FooType) foo;
}
}
然后我可以要求我的 getFoo 方法属于这种类型:
public FooResult getFoo(boolean which) {
return which ? new FooResult(new TrueFoo()) : new FooResult(new WrongFoo());
}
那样,我将无法从我的 get 方法返回 WrongFoo。
但是,很明显,这有点过于复杂,无法像 Java 泛型通常倾向于编写代码那样优雅(根据我的经验)......那么,可以以某种方式缩短它吗?
编辑 3:
我找到了另一种方法来为实现接口的人提供检查,方法是这样定义:
interface Foo<FooType extends Foo<FooType>> {
// Other interface definitions
/**
* Please implement with just this line in it:<br/><br/>
* <code>return this;</code>
* @return <code>this</code>
*/
public FooType returnThis();
}
现在,如果有人尝试实现上述 WrongFoo 类,他将必须提供方法 FalseFoo returnThis(),如果他只是按照 doctype 中的要求将其实现为 return this,则该行将引发错误。
这不是保证,但它是一个很好的虚拟检查,可以防止因粗心复制类而产生的错误......而且在无论如何都需要带有此签名的消息的情况下,这将是一个很好的解决方案。
还有什么想法吗?
【问题讨论】:
-
这是一个有趣的问题,但它确实令人困惑。与其试图如此笼统,不如加入一些真实姓名。那些傻瓜很难跟上
-
@hbtest True...我正在尝试考虑是否有更好的方法可以以这种方式思考...有什么想法吗?
-
这只是一个笼统的问题,还是您实际上有这种情况?我假设您在某种情况下遇到过这种情况,如果是这样,请发布。
-
我确实在我的代码中遇到过它,但是上下文非常复杂,我试图尽可能地将问题提炼为实际的问题。
-
我很难为您提供帮助,因为我自己无法理解它......对不起
标签: java generics methods return-type