重载方法

时间:2016-09-29 13:28:37

标签: java generics overloading

我有以下类型化接口层次结构和一个实现:

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);
}

现在我试图用两种不同类型的Float和Integer故意调用calculate():

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

一旦我调用它,Java就会一直引用add(Float,Float)方法,并且看不到重载方法add(Float,Integer)。

IDEA建议“未选中调用添加(T,T)作为原始类型的成员......”

如何修改我的接口/类以便能够根据需要使用重载方法?

2 个答案:

答案 0 :(得分: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));
        }

答案 1 :(得分:0)

如果使用接口OperationNumeric operand声明的变量对象,则只能使用此接口中声明的方法。实例化对象的其余方法不可见。尝试正确定义对象,如:

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