简体   繁体   English

Java子类不识别其通用超类

[英]Java subclass does not recognise its generic superclass

I need help with a problem I have with generics in Java. 我需要帮助解决Java中的泛型问题。 I'm writing this Computer algebra system, where the user enters a math expression and the system works with it in different ways (expand it, simplify it etc). 我正在编写这个计算机代数系统,用户输入数学表达式,系统以不同的方式使用它(扩展它,简化它等)。 It worked fine for expressions containing natural numbers, and I wanted to expand it to work with mathematical sets as well. 它适用于包含自然数的表达式,我想扩展它以使用数学集。 Instead of +, you would have the intersection operator, etc. 而不是+,你将拥有交叉算子等。

At first, I started recording everything for the sets, but then I realized this was probably not good and started using generics. 起初,我开始记录集合的所有内容,但后来我意识到这可能并不好,并开始使用泛型。

Instead of having one parse tree like MathExpr and one like SetExpr , I thought I could just have a generic Expression<T> and build a base class Number and a base class Set . 相反,有一个解析树像MathExpr和一个像SetExpr ,我想我可能只是有一个通用的Expression<T>建立一个基类Number和一个基类Set

To try to clarify, I want a mathematical expression like (2 * a) + (3 + 2) to be an instance of a class Expression<Number> and a set expression like (A ∪ B) ∩ C to be an instance of Expression<Set> . 为了澄清,我希望像(2 * a)+(3 + 2)这样的数学表达式是类Expression<Number>的实例,并且像(A∪B)∩C这样的集合表达式是一个实例Expression<Set> I can then perform different operations on this, like calculate the depth etc. 然后,我可以对此执行不同的操作,例如计算深度等。

The + operation is implemented as one class, the * as one class etc. Both these classes are subclasses of an abstract class called TwoExpr which in turn is a subclass of the abstract class Expr . +操作实现为一个类,*作为一个类等。这两个类都是一个名为TwoExpr的抽象类的子类,而后者又是抽象类Expr的子类。 This is how I have done it now and everything works fine. 这就是我现在做的一切,一切正常。

When I wanted to change my code I made my Expr class generic. 当我想要更改我的代码时,我使我的Expr类变得通用。 That is Expr<T> . 那是Expr<T> I also changed TwoExpr to TwoExpr<T> and created a base class Number . 我还将TwoExpr更改为TwoExpr<T>并创建了一个基类Number

The problem is, now I can't seem to instantiate objects of the type Sum<Number> . 问题是,现在我似乎无法实例化Sum<Number>类型的对象。

I get a " Type mismatch: cannot convert from Sum to Expr<Number> " error. 我得到“ Type mismatch: cannot convert from Sum to Expr<Number> ”错误。 But Sum is a subclass of TwoExpr<Number> , which in turn is a subclass of Expr<Number> . SumTwoExpr<Number>的子类,它又是Expr<Number>的子类。 As you may realize, I can't make the class Sum generic and call it Sum<Number> , because all arithmetic operations don't have analogues for sets. 正如您可能意识到的那样,我不能使类Sum通用并将其称为Sum<Number> ,因为所有算术运算都没有集合的类似物。

I have always been able to create objects like 我一直能够创建像

Expr zero= new Leaf(0);
Variable a = new Variable("a");
Expr aPlusZero = new Sum(a, zero);

When I changed to generics, the same code looks like this: 当我更改为泛型时,相同的代码如下所示:

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

How come it doesn't recognize that Sum(a,zero) is a subclass of Expr<Number> , when it says in the declaration of Sum 为什么它不能识别Sum(a,zero)Expr<Number>的子类,当它在Sum的声明中说

public class Sum extends TwoExpr<Number> {

    public Sum(Expr<Number> a, Expr<Number> b) {
        super(a, b);
    }
...
}

and in the declaration of TwoExpr 并在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;
    }
    ...
}

I know that Lizkows substitution principle doesn't apply for generic arguments. 我知道Lizkows替换原则不适用于泛型参数。 But Number isn't a subclass of anything (except Object) and don't have any subclasses. 但Number不是任何子类(Object除外),并且没有任何子类。 I hope I've been fairly clear about what I'm trying to do and what problem I have. 我希望我已经相当清楚我正在尝试做什么以及我有什么问题。 Does anybody have any idea how to solve it? 有谁知道如何解决它? Please tell me if anything was unclear in the above or if you want more code. 如果上面有任何不清楚的地方或者您想要更多代码,请告诉我。

Thanks in advance. 提前致谢。

Mattias 马蒂亚斯

I think your problem is in the classes you did not show, I tried the following and it works: 我认为你的问题出在你没有展示的课程中,我尝试了下面的工作:

Expr<Number> zero= new Expr<Number>();
Expr<Number> a= new Expr<Number>(); 
Expr<Number> APlusZero=new Sum(a,zero);

Might it be that Variable is not an Expr? 可能是变量不是Expr?

UPDATE: 更新:

I played a little creating Variable and Leaf as I imagine them and it all works: 我玩了一点创建变量和叶子,因为我想象它们一切正常:

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

If you take the extends Expr from Variable it does give the error you experience, might it be this the cause? 如果从变量中获取扩展的Expr,它确实会给出您遇到的错误,这可能是原因吗?

Maybe try to debug it: 也许尝试调试它:

Object = new Sum(a,zero);
System.out.println(o.getClass().getGenericSuperclass());

Furthermore maybe is a better solution for your system. 此外,对您的系统来说可能是更好的解决方案

Sum does not import Types.Number . Sum不会导入Types.Number So it's not Expr<Types.Number> but Expr<java.lang.Number> . 所以它不是Expr<Types.Number>而是Expr<java.lang.Number> I would assume this would give a compilation error not only on the assignment but also on the construction of new Sum(vA, zero) , but maybe the compiler sees the other error first. 我认为这不仅会在赋值时产生编译错误,而且会在构造new Sum(vA, zero)产生编译错误,但编译器可能会先看到其他错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM