gpt4 book ai didi

java - 强制 Java 方法返回类型以适应特定的通用签名

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:54:44 25 4
gpt4 key购买 nike

假设我有这个界面:

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 的实例调用它,这将给您一个绑定(bind)不匹配错误。

让我觉得应该有一种方法可以对方法返回类型执行此操作。

或者有没有办法在 Foo 的接口(interface)定义中强制执行此签名?

编辑:

为了帮助形象化这个界面应该做什么,你可以想象它的这个版本:

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)的人提供检查,方法如下:

interface Foo<FooType extends Foo<FooType>> { 
// Other interface definitions

/**
* Please implement with just this line in it:<br/><br/>
* &nbsp;&nbsp;&nbsp;&nbsp;<code>return this;</code>
* @return <code>this</code>
*/
public FooType returnThis();
}

现在,如果有人试图实现上面描述的 WrongFoo 类,他将不得不提供方法 FalseFoo returnThis()如果他只是将其实现为 return this按照 doctype 中的要求,该行将引发错误。

这不是保证,但它是一个很好的虚拟检查,可以防止因粗心复制类而导致的错误……并且在无论如何都需要具有此签名的消息的情况下,这将是一个很好的解决方案。

还有什么想法吗?

最佳答案

您遇到的泛型问题是症状,而不是问题所在:您要求您的界面依赖于您的具体实现。如果您希望 getFoo 接口(interface)方法返回不是 WrongFoo 的内容,则必须返回 TrueFoo 或 FalseFoo 但不是 WrongFoo 的内容。您的类层次结构没有这种特定的间接寻址。

要添加它,您需要执行以下操作:

class TrueFoo extends SpecialFoo {...}

class FalseFoo extends SpecialFoo {...}

class WrongFoo implements Foo<WrongFoo> {...}

class SpecialFoo implements Foo<SpecialFoo> {
SpecialFoo getFoo() {...}
}

请记住,Java 支持协变返回类型,因此通过返回 SpecialFoo,我们可以实现在 Foo 接口(interface)中创建的契约:Foo getFoo() {...}

如果您需要特定于 TrueFoo 和 FalseFoo 的行为,您可以进一步参数化 SpecialFoo,等等,turtles all the way down .

编辑:

阅读您的编辑后,我认为该语言不支持您要实现的目标。似乎您想根据具体实现来约束接口(interface),根据定义,这将使其不是接口(interface)。我认为以下示例非常接近您要查找的内容:

interface CanCopy<T extends CanCopy<T>> {
T copy();
}

interface FooCanCopy extends CanCopy<Foo> {
}

interface BarCanCopy extends CanCopy<Bar> {
}

class Foo implements FooCanCopy {

public Foo copy() {
return null;
}
}

class Bar implements BarCanCopy {

public Bar copy() {
return null;
}
}

我希望它现在清楚为什么该方法不起作用,即使在这里你仍然不能阻止某人做类似 class Baz implements FooCanCopy 的事情。我更想知道你为什么要这样做?如果是为了保护开发人员不犯错误,可能还有其他选择,即内省(introspection)单元测试或打包更改。

关于java - 强制 Java 方法返回类型以适应特定的通用签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13637882/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com