Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java subclass does not recognise its generic superclass

I need help with a problem I have with generics in 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.

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>. 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. 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. That is Expr<T>. I also changed TwoExpr to TwoExpr<T> and created a base class Number.

The problem is, now I can't seem to instantiate objects of the type Sum<Number>.

I get a "Type mismatch: cannot convert from Sum to Expr<Number>" error. But Sum is a subclass of TwoExpr<Number>, which in turn is a subclass of 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.

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

public class Sum extends TwoExpr<Number> {

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

and in the declaration of 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. But Number isn’t a subclass of anything (except Object) and don't have any subclasses. 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

like image 781
Mattias Avatar asked Aug 10 '26 04:08

Mattias


1 Answers

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?

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?

like image 91
Miquel Avatar answered Aug 11 '26 17:08

Miquel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!