2

首先,我想说这没有用例。我唯一想做的就是探索这是否可能。

我想要做的是将基本接口中方法的返回签名“重新命名”为子接口的返回签名。

目标:声明和实现一个方法一次,但改变返回类型以匹配子接口。我已经想出了在某些情况下如何实现这一点,但在某些情况下它会崩溃。

想象一下,如果我有基本接口 B,并且它有一个方法 B doWork()。此外,还有一个实现 doWork() 的 B 实现。由于 doWork() 的性质,这个实现应该是唯一存在的。

现在,使用泛型很容易做到这一点。对于上面的例子:

interface B<T extends B> {
    T doWork();
}

class BImpl<T extends B> implements B<T> {
    @Override
    public T doWork() { return something; }
}

子接口/实现可能看起来像这样:

interface C extends B<C> {
    void somethingCSpecific();
}

class CImpl extends BImpl<C> implements C {
    @Override
    public void somethingCSpecific() {   }
}

任何构建 CImpl 的人都会看到 doWork() 返回一个 C。

C obj = new CImpl().doWork()  // The money shot.  No casting needed.

这就是它崩溃的地方......想象B现在看起来像这样:

public interface B<T extends B> {
    T thisOrThat(T that);
    boolean something();
}

我想在 BImpl 中做到这一点:

class BImpl<T extends B> implements B<T> {
    @Override
    public T thisOrThat(T that) {
        if (that.something())
            return that;
        return this;  //  Error!!  _this_ might be a different T than _that_.
    }
    @Override
    public boolean something()  { return whatever; }
}

注意错误发生的位置。

显然,如果没有不安全和可疑的演员阵容,这是行不通的。但是如果我知道上面 thisOrThat 方法中this的实现与that的实现是一样的,一切都会好起来的。

所以,对于我的问题。有没有办法在不知道先验类型的情况下将这个那个限制为同一类型?

或者也许有不同的方法可以做到这一点,但结果相同?即只需声明并实现 thisOrThat() 一次,但返回类型是否适应子接口?

谢谢。

4

2 回答 2

3

使您的类BImpl抽象并为其添加一个视图方法,该方法由扩展您的抽象基类的特定类实现:

public abstract class BImpl<T extends B<T>> implements B<T> {
   @Override
   public T thisOrThat(T that) {
       if (that.something())
           return that;
       return this.asT();
   }


    @Override
    public boolean something() {
        // TODO Auto-generated method stub
        return false;
    }

    protected abstract T asT();
}

您的每个类仍然需要实现T asT(),但这很简单并且可以在没有警告的情况下编译:

public class C extends BImpl<C> implements B<C> {
    @Override
    protected C asT() {
        return this;
    }
}
于 2012-04-18T22:49:58.310 回答
2

如果我正确理解您的问题,那么解决它的方法是使用一种自引用泛型:B<T extends B<T>>.

我认为您想要的是class BImpl implements B<BImpl>,在这种情况下,所有类型都会正常检查。

于 2012-04-18T21:46:02.350 回答