我需要帮助解决Java中泛型问题。我正在编写这个计算机代数系统,用户输入数学表达式,系统以不同的方式使用它(扩展它,简化它等)。它适用于包含自然数的表达式,我想扩展它以使用数学集。而不是+,你将拥有交叉算子等。
起初,我开始记录集合的所有内容,但后来我意识到这可能不太好并开始使用泛型。
我没有像MathExpr
这样的一个解析树而是像SetExpr
这样的解析树,而是认为我可以只使用通用Expression<T>
并构建基类Number
和基础班Set
。
为了澄清,我想要一个像(2 * a)+(3 + 2)这样的数学表达式作为类Expression<Number>
的实例和一个像(A∪B)∩C到的集合表达式是Expression<Set>
的一个实例。然后我可以对此执行不同的操作,例如计算深度等。
+操作实现为一个类,*作为一个类等实现。这两个类都是一个名为TwoExpr
的抽象类的子类,它又是抽象类Expr
的子类。这就是我现在所做的一切,一切正常。
当我想要更改我的代码时,我将Expr
类设为通用。那是Expr<T>
。我还将TwoExpr更改为TwoExpr<T>
并创建了基类Number
。
问题是,现在我似乎无法实例化Sum<Number>
类型的对象。
我收到“Type mismatch: cannot convert from Sum to Expr<Number>
”错误。但Sum
是TwoExpr<Number>
的子类,而后者又是Expr<Number>
的子类。正如您可能意识到的那样,我无法使类Sum
成为泛型并将其称为Sum<Number>
,因为所有算术运算都没有集合的类似物。
我一直能够创建像
这样的对象Expr zero= new Leaf(0);
Variable a = new Variable("a");
Expr aPlusZero = new Sum(a, zero);
当我更改为泛型时,相同的代码如下所示:
Expr<Number> zero= new Leaf<Number>(new Number(0)); //works fine
Variable<Number> a = new Variable<Number>("a"); //works fine
Expr<Number> APlusZero=new Sum(a,zero); //gives a "Type mismatch:
//cannot convert from Sum to Expr<Number>" error
为什么它不能识别Sum(a,zero)
是Expr<Number>
的子类,当它在Sum的声明中说明时
public class Sum extends TwoExpr<Number> {
public Sum(Expr<Number> a, Expr<Number> b) {
super(a, b);
}
...
}
并在TwoExpr的声明中
public abstract class TwoExpr<T> extends Expr<T> {
protected Expr<T> a;
protected Expr<T> b;
public TwoExpr(Expr<T> a, Expr<T> b) {
this.a=a;
this.b=b;
}
...
}
我知道Lizkows替换原则不适用于泛型参数。但Number不是任何子类(Object除外),并且没有任何子类。 我希望我已经相当清楚我正在尝试做什么以及我有什么问题。有谁知道如何解决它?如果上面有任何不清楚的地方,或者你想要更多的代码,请告诉我。
提前致谢。
的Mattias
答案 0 :(得分:2)
我认为您的问题出在您未展示的课程中,我尝试了以下内容并且有效:
Expr<Number> zero= new Expr<Number>();
Expr<Number> a= new Expr<Number>();
Expr<Number> APlusZero=new Sum(a,zero);
可能是变量不是Expr?
更新:
我按照我想象的方式创建了一个创建变量和叶子的东西,这一切都有效:
public class Number {
public Number(int i){}
}
public class Variable<T> extends Expr<T> {
public Variable(String s){}
}
public class Leaf<T> extends Expr<T> {
public Leaf(T t) {
super();
}
}
public class Expr<T> {
}
public class TwoExpr<T> extends Expr<T> {
public TwoExpr(Expr<T> a, Expr<T> b) {
}
}
public class Sum extends TwoExpr<Number> {
public Sum(Expr<Number> a, Expr<Number> b) {
super(a, b);
}
}
public class AllTogether {
public static void main(String[] args) {
Expr<Number> zero= new Leaf<Number>(new Number(0));
Variable<Number> a = new Variable<Number>("a");
Expr<Number> APlusZero=new Sum(a,zero);
}
}
如果从变量中获取扩展的Expr,它确实会给出您遇到的错误,这可能是原因吗?
答案 1 :(得分:0)
也许尝试调试它:
Object = new Sum(a,zero);
System.out.println(o.getClass().getGenericSuperclass());
此外,对您的系统来说,这可能是更好的解决方案。
答案 2 :(得分:0)
Sum
不会导入Types.Number
。所以它不是Expr<Types.Number>
而是Expr<java.lang.Number>
。我认为这不仅会在赋值时产生编译错误,而且会在new Sum(vA, zero)
的构造上产生编译错误,但编译器可能会先看到另一个错误。