[英]How can I limit a method to only accept parameters with certain restrictions?
我有以下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編寫的
您不能擁有僅存在於類的某些實例中的方法。
相反,您可以將約束放在類的類型參數上。
在Java中,確實沒有很好的方法來執行此操作。 該語言不支持在Number
任意子類上均可使用的任何類型的“ add”或“ plus”功能。
但是,我發現了一種解決該問題的方法。 它要求您設置一個映射,將您感興趣的每個數字類映射到一個將對該類添加兩個數字的函數,然后在運行時查找該函數。 這使用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)
(這使用了一些原始類型,但是我不知道如何解決。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.