我有以下类型化接口层次结构和一个实现:
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)作为原始类型的成员......”
如何修改我的接口/类以便能够根据需要使用重载方法?
答案 0 :(得分: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));
}
答案 1 :(得分:0)
如果使用接口OperationNumeric operand
声明的变量对象,则只能使用此接口中声明的方法。实例化对象的其余方法不可见。尝试正确定义对象,如:
if (operand instanceof OperationFloat && operand2 instanceof Integer) {
((OperationFloat) operand).add(operand1, (Integer)operand2);
}