[英]How can I limit a method to only accept parameters with certain restrictions?
I have the following Duple class, and I'm trying to write methods to perform math over both of its "cells" ((new Duple(1,2)).plus(new Duple(2,6) == new Duple(3,8))
: 我有以下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);
}*/
The commented-out code gives an error because it can't guarantee that T
or U
will support +
. 注释掉的代码给出了错误,因为它不能保证
T
或U
将支持+
。 Is there a way to have it do a compile time check on the parameters? 有没有一种方法可以对参数进行编译时检查?
I tried: 我试过了:
public Duple<T,U> plus(Duple <T extends Number,U extends Number> otherDuple) { ... }
But the compiler complains for me to delete extends
. 但是编译器为我抱怨删除
extends
。 I saw an example using a user defined interfaces, but for what I need it for, that seems extreme. 我看到了一个使用用户定义的接口的示例,但是对于我需要的接口,这似乎很极端。
Basically I'm trying to emulate: 基本上,我试图模仿:
plus :: (Num t, Num u) => Duple t u -> Duple t u -> Duple t u
(x1,y1) `plus` (x2,y2) = (x1 + x2,y1 + y2)
If it were written in Haskell 如果是用Haskell编写的
You cannot have a method that only exists on some instantiations of your class. 您不能拥有仅存在于类的某些实例中的方法。
Instead, you can put the constraints on the class's type parameters. 相反,您可以将约束放在类的类型参数上。
There really isn't a good way to do this in Java; 在Java中,确实没有很好的方法来执行此操作。 the language doesn't support any kind of "add" or "plus" function that will work on any arbitrary subclass of
Number
. 该语言不支持在
Number
任意子类上均可使用的任何类型的“ add”或“ plus”功能。
However, I've found a rather hack-ish way to work around it. 但是,我发现了一种解决该问题的方法。 It requires that you set up a map that maps each numeric class you're interested in to a function that will add two numbers of that class, and then looking up the function at runtime.
它要求您设置一个映射,将您感兴趣的每个数字类映射到一个将对该类添加两个数字的函数,然后在运行时查找该函数。 This uses Java 8:
这使用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));
}
}
My test program: 我的测试程序:
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);
}
and the output is what you'd expect: 输出是您期望的:
(9, 6.2)
(4.8, 37)
(This uses some raw types, but I don't know of a way around that.) (这使用了一些原始类型,但是我不知道如何解决。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.