像这样的基类:
public abstract class Addable<T extends Number,U extends Addable<T,U>> { private final T value; public Addable( final T value ){ this.value = value; } public T getValue(){ return value; } public abstract U add( U addend ); }
而这作为子类:
public class AddableInteger extends Addable<Integer,AddableInteger> { public AddableInteger( final Integer value ){ super( value ); } @Override public AddableInteger add( final AddableInteger addend ){ java.util.Objects.requireNonNull( addend ); return new AddableInteger( this.getValue() + addend.getValue() ); } }
那么,在C ++中工作的原因是编译器将创建与代码中的调用一样多的函数,并独立编译每个函数以验证在该特定情况下“+”是否是合理的事情。这有点像编译器辅助的鸭子打字。换句话说,不能保证类型T将具有+运算符,并且只保证编译器将查看实际的调用类型并创建排列有助于您。
请注意,让编译器“添加任何内容”存在一些风险,因为没有保证语义正确的接口或契约。这就是类层次结构带给你的东西。
这在完全类型安全性方面比较棘手,因为继承可能很复杂,返回类型需要有些清晰。继承是通常的事情,因此虚方法知道如何添加自己的类型,但在这种情况下,您不能更改Number的类层次结构。
不过,你可以这样做:
public static int addAsInt(Number a, Number b) { a.intValue() + b.intValue(); }
其他返回类型也是如此。这将采用任意两个数字实例并生成输出值,假设您需要哪种输出类型。比在这种特殊情况下创建包装类要容易一些。