我想做的事情:
我正在创建一个类层次结构,它代表并具有许多线性代数概念的实用工具(用于练习线性代数和练习Java,我现在正在学习)。 一切顺利,直到我决定添加不同类型的数字,即整数,有理数,实数和复数(现在)。
我想要的是能够与它们一起操作(例如,在Matrix类中)而不必关心我操作的数字类型,并在代表每个数字的不同类中实现所有操作类型。
我的想法/尝试:
我认为制作名为" AnyNumber"的界面是个好主意。 (因为Number已由Java API使用),我在其上定义了所有必需的抽象方法,然后在每个数字类型类上实现该接口。 问题是,我无法弄清楚如何处理类类型。
这是接口声明的样子:
public interface AnyNumber {
public AnyNumber add(AnyNumber other);
public AnyNumber subtract(AnyNumber other);
public AnyNumber multiply(AnyNumber other);
public AnyNumber divide(AnyNumber other);
}
这样,我就可以通过简单的调用方法操作任何实现接口的对象:
number1 = number1.add(number2)
我遇到的问题
尝试在特定类上实现接口方法时出现问题 我以为Java知道类型" AnyNumber"可以是任何实现接口的类型,所以我尝试声明这样的方法:
public IntegerNumber add(IntegerNumber other) {
return new IntegerNumber(this.value + other.value);
}
但Eclipse抱怨说我没有实现以下方法:
AnyNumber add(AnyNumber other)
然后我虽然我可以将返回和参数类型更改为" AnyNumber"但很快就意识到我无法访问变量" value"在里面"其他"因为界面没有定义它。
所以我想也许我需要的是一个抽象类,它为所有不同类型的数字定义了所有必要的字段和抽象方法,但我不确定这是否是一个很好的方法,因为整数数字只需要一个字段,而理性需要两个,复杂需要两个,但我想将它们命名为不同。此外,有些事情告诉我在这种情况下界面很有意义。
..所以我可能也许我需要的是泛型。但是我还没有完全理解它们,而我用它们解决这个问题的所有尝试都失败了。
请帮忙
我意识到我无法单独解决这个问题......我真的想继续研究这个项目并学习如何用Java来处理这种情况。
非常感谢您的帮助!
答案 0 :(得分:2)
实现接口方法时,参数类型必须与接口中的参数类型完全相同。 return 类型不必相同 - 它可以是子类(这称为协方差)。但参数类型不能是子类(这称为逆变,Java不允许它)。
原因是没有什么能阻止两个AnyNumber
对象的类型不同。
AnyNumber n1 = new IntegerNumber(123);
AnyNumber n2 = new RealNumber(23.4);
然后,你可以说:
IntegerNumber n3 = n1.add(n2);
或者您可以将n1
和n2
作为参数传递给尝试执行上述操作的其他方法。这里的要点是,由于n1
和n2
被声明为AnyNumber
,因此编译器无法判断这两个对象是否具有相同的类。
这意味着如果您要求两个对象具有相同的类,则必须在运行时自行强制执行。
您的实现类需要看起来像
public class IntegerNumber implements AnyNumber {
public IntegerNumber add(AnyNumber other) { // NOTE: Must be AnyNumber!!
IntegerNumber otherInteger = (IntegerNumber)other;
// will throw a ClassCastException at runtime if "other" is, say, RealNumber
...
}
}
该方法的其余部分可以使用otherInteger
,由于您已经检查过,编译器知道此时将是IntegerNumber
。你还可以做其他事情;你可以使用instanceof
来检查,并控制你抛出的异常(或你做了什么),而不是让强制转换抛出异常。如果选择,您还可以添加处理不同AnyNumber
类型添加的机制。