我有以下Duple类,我试图编写方法来对其两个"单元格进行数学运算。 ((new Duple(1,2)).plus(new Duple(2,6) == new Duple(3,8))
:
final class Duple<T,U> {
final T a;
final U b;
public Duple(T a, U b) { this.a = a; this.b = b; }
public String toString() {
return "(" + a + ", " + b + ")";
}
/*public Duple<T,U> plus(Duple <T,U> otherDuple) {
return Duple(a + otherDuple.a, b + otherDuple.b);
}*/
注释掉的代码会出错,因为它无法保证T
或U
支持+
。有没有办法让它对参数进行编译时检查?
我试过了:
public Duple<T,U> plus(Duple <T extends Number,U extends Number> otherDuple) { ... }
但是编译器抱怨我要删除extends
。我看到了一个使用用户定义接口的例子,但是对于我需要的东西,这看起来很极端。
基本上我试图模仿:
plus :: (Num t, Num u) => Duple t u -> Duple t u -> Duple t u
(x1,y1) `plus` (x2,y2) = (x1 + x2,y1 + y2)
如果它是用Haskell编写的
答案 0 :(得分:1)
您不能拥有仅存在于您的类的某些实例中的方法。
相反,您可以将约束放在类的类型参数上。
答案 1 :(得分:1)
在Java中实现这一点并不是一个好方法。该语言不支持任何类型的&#34;添加&#34;或&#34;加&#34;适用于Number
的任意子类的函数。
然而,我发现了一种相当黑客的解决方法。它要求您设置一个映射,将您感兴趣的每个数字类映射到一个函数,该函数将添加该类的两个数字,然后在运行时查找该函数。这使用Java 8:
final class Duple<T,U> {
final T a;
final U b;
public Duple(T a, U b) { this.a = a; this.b = b; }
public String toString() {
return "(" + a + ", " + b + ")";
}
private static Map<Class,BinaryOperator> adders = new HashMap<>();
private static <T> void setAdder(Class<T> forClass, BinaryOperator<T> adder) {
adders.put(forClass, adder);
}
private static void setAdders() {
setAdder(Integer.class, (x, y) -> x + y);
setAdder(Long.class, (x, y) -> x + y);
setAdder(Float.class, (x, y) -> x + y);
setAdder(Double.class, (x, y) -> x + y);
setAdder(BigInteger.class, (x, y) -> x.add(y));
// add more as desired
}
static {
setAdders();
}
private static <T1> T1 add(T1 x, T1 y) {
BinaryOperator adder = adders.get(x.getClass());
if (adder == null) {
throw new RuntimeException("No plus operation defined for class");
}
return (T1)adder.apply(x, y);
}
public Duple<T,U> plus(Duple <T,U> otherDuple) {
return new Duple(add(this.a, otherDuple.a), add(this.b, otherDuple.b));
}
}
我的测试程序:
public static void main(String[] args) {
Duple<Long,Double> x1, x2, x3;
Duple<Float,BigInteger> x4, x5, x6;
x1 = new Duple<>(3L, 4.0);
x2 = new Duple<>(6L, 2.2);
x3 = x1.plus(x2);
System.out.println(x3);
x4 = new Duple<>(1.7F, BigInteger.valueOf(15));
x5 = new Duple<>(3.1F, BigInteger.valueOf(22));
x6 = x4.plus(x5);
System.out.println(x6);
}
并且输出是您所期望的:
(9, 6.2)
(4.8, 37)
(这使用了一些原始类型,但我不知道如何解决这个问题。)