实现逆变参数的泛型类型

Jac*_*chi 0 java generics

让我们考虑一下这段代码:

public interface Number {
  public Number plus(Number n);
}

public class Complex implements Number {
  private double re, im;

  public Complex(double re, double im) {
    this.re = re;
    this.im = im;
  }

  @Override
  public Complex plus(Complex c) {
    return new Complex(this.re + c.re, this.im + this.im);
  }
}
Run Code Online (Sandbox Code Playgroud)

它不会编译,因为如果Complex.plus()overrides Number.plus(),它的参数必须与被覆盖的方法完全相同。我想过对数字可以与之交互的对象类型使用泛型,但它产生了一个非常不干净的代码,没有参数化的使用Number和冗余:

public interface Number<T extends Number> {
    public T plus(T n);
}

public class Complex implements Number<Complex> {
    private double re, im;

    public Complex(double re, double im) {
        this.re = re;
        this.im = im;
    }

    @Override
    public Complex plus(Complex c) {
        return new Complex(this.re + c.re, this.im + this.im);
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有更优雅的方法来实现这一目标?

感谢您的帮助。

And*_*ner 5

简单修复:使类型参数自有界:

public interface Number<T extends Number<T>> {
Run Code Online (Sandbox Code Playgroud)

(然后小指发誓你只会定义一个为自己实现接口的类,例如class Self implements Number<Self>


但是,我会在没有Number接口的情况下做到这一点,至少在plus方法方面。除非您可以有意义地添加 的不同子类型,否则Number在公共接口中使用这样的方法显然没有任何意义。

考虑为什么没有在标准Number接口上定义算术方法。

相反,类中也不要有plus“运算符” Complex:使用标准BinaryOperator接口为特定类型定义加号运算符:

BinaryOperator<Complex> complexPlus = (a, b) -> new Complex(a.re + b.re, a.im + b.im);
BinaryOperator<Integer> integerPlus = (a, b) -> a + b; // Or Integer::sum.
Run Code Online (Sandbox Code Playgroud)

然后应用这些:

Complex complexSum = complexPlus.apply(firstComplex, secondComplex);
Integer integerSum = integerPlus.apply(firstInt, secondInt); 
Run Code Online (Sandbox Code Playgroud)