2016-09-29 5 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); 
} 

Теперь я пытаюсь вызвать метод calc() намеренно w Ith два различных типа Float и целое, как это:

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

После того, как я это называю, Java продолжает со ссылкой на добавление (Float, Float) метод и не может видеть перегруженный метод добавления (Float, Integer).

IDEA предлагает «Неконтролируемый призыв добавить (T, T) в качестве члена сырого типа ...»

Как изменить мои интерфейсы/классы, чтобы иметь возможность использовать перегруженный метод, как я хочу?

+0

Это интересно. Я думал, что Java увидит '2' как int и будет использовать подпись Integer. Что происходит, когда вы завершаете '2' в' Integer (2) '? –

+6

'add (Float, Integer)' не является частью интерфейса. Почему Java должен использовать этот метод, если вы работаете с интерфейсом 'OperationNumeric'? – 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> (поскольку Integer и Float не имеют прямого отношения наследования).

Если вы хотите использовать разные типы для обоих параметров, вам действительно понадобятся три общих параметра (по одному для каждого параметра и один для типа возврата). Это приведет к интерфейсу, как это:

/** 
* @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

Спасибо. Я, вероятно, займусь этим решением! –