2016-09-29 79 views
1

我的類型化的接口下面的層級和一個實現:Java泛型與重載方法的問題

public interface Operation<T> { 

    T add(T object1, T object2); 
} 

public interface OperationNumeric<T extends Number> extends Operation<T> { 

     T add(T number1, T number2); 
} 

實施這一項目有一個重載方法Add():

public class OperationFloat implements OperationNumeric<Float> { 

     public Float add(Float number1, Float number2) { 
       return number1+number2; 
     } 

     public Float add(Float number1, Integer number2) { 
       return number1+number2; 
     } 
    } 

現在我有一個使用OperationNumericInterface的方法:

public Number calculate(Number operand1, Number operand2, OperationNumeric operand) throws Exception { 
     return operand.add(operand1, operand2); 
} 

現在我試圖調用calculate()故意w第i兩種不同類型Float和整數這樣的:

try { 
     calculate(2.2f,2, new OperationFloat()); 
    } catch (Exception e) { 
     System.out.println(e.getMessage()); 
} 

有一次,我把它叫做,Java的不斷提及加(浮動,浮動)方法,並不能看到重載的方法加上(浮點,整數)。

IDEA提示「未調用(T,T)添加爲原料類型的成員......」

如何修改我的接口/類能夠使用重載的方法,因爲我想要的嗎?

+0

這很有趣。我以爲Java會將'2'看作int並使用'Integer'簽名。在'Integer(2)'中包裝'2'時會發生什麼? –

+6

'add(Float,Integer)'不是接口的一部分。如果您在'OperationNumeric'界面上操作,爲什麼Java應該調用此方法? – Turing85

+0

[重載的方法選擇基於參數的實際類型]可能的重複(http://stackoverflow.com/questions/1572322/overloaded-method-selection-based-on-the-parameters-real-type) – Tom

回答

0

如果您正在使用由接口OperationNumeric operand聲明的變量對象,則只能使用在此接口中聲明的方法。實例化對象的其餘部分不可見。嘗試正確定義諸如對象:

if (operand instanceof OperationFloat && operand2 instanceof Integer) { 
    ((OperationFloat) operand).add(operand1, (Integer)operand2); 
} 
3

在解決方案中的基本缺陷就是Operation界面中的兩個操作數必須是同一類型的。因此,方法Float add(Float, Integer)通過接口OperationNumeric<Float>不可見(因爲IntegerFloat沒有直接的繼承關係)。

如果你想爲兩個參數使用不同的類型,你實際上需要三個通用參數(每個參數一個,返回類型一個)。這將導致這樣的接口:

/** 
* @param <O> first parameter-type of operation 
* @param <P> second parameter-type of operation 
* @param <R> result-type of operation 
*/ 
public interface OperationNumeric<O extends Number 
            , P extends Number 
            , R extends Number> { 
    R add(O number1, P number2); 
} 

此接口然後將這樣被實現:

OperationNumeric<Float, Float, Float> floatAddition 
    = (Float f1, Float f2) -> { 
     return (f1 + f2); 
    }; 

OperationNumeric<Float, Integer, Float> floatIntAddition 
    = (Float f, Integer i) -> { 
     return (f + i); 
    }; 

OperationNumeric<Number, Number, Number> numberAddition 
    = (Number n1, Number n2) -> { 
     return (n1.doubleValue() + n2.doubleValue()); 
    }; 
... 

通告numberAddition的例子。這大概是最接近你真正想要達到的。如果你看一下實現,你會發現這個操作是在double值上完成的,因此你鬆開了一些特定類型的屬性(例如,在循環算術中不會完成加法操作,分割時的最低值爲int ...)。可以通過添加一堆instanceof這樣的檢查來解決這個問題:

 if ((n1 instanceof Integer) && (n2 instanceof Integer)) { 
      return (((Integer) n1) + ((Integer) n2)); 
     } 
+0

謝謝。我可能會用這個解決方案! –