Java子类不识别其通用超类

时间:2011-03-21 23:06:18

标签: java generics inheritance

我需要帮助解决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>”错误。但SumTwoExpr<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

3 个答案:

答案 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)的构造上产生编译错误,但编译器可能会先看到另一个错误。