簡體   English   中英

如何將方法限制為僅接受具有特定限制的參數?

[英]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);
    }*/

注釋掉的代碼給出了錯誤,因為它不能保證TU將支持+ 有沒有一種方法可以對參數進行編譯時檢查?

我試過了:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM