简体   繁体   中英

How can i create a constructor with generics with same class as argument

I have a class Expression:

public class Expression < E extends Number, V extends Number >
{
   public Expression(E lV, OPERATION operation, V rV) {
   }

   public Expression(Expression< E, V > lE, OPERATION operation, Expression< E, V > rE) {
   }
}

Expression.java compile without errors.

This is my main class code.

public static void main(String[] args)
{
        // Line 1. 
    refactored.Expression< ?, ? > ex1 = new refactored.Expression< Double, Float >(10d, OPERATION.PLUS, 10f);

        // Line 2.
    refactored.Expression< ?, ? > ex2 = new refactored.Expression< Double, Float >(-3d, OPERATION.MUL, 1f);

        // Line 3.
    refactored.Expression< ?, ? > ex3 = new refactored.Expression< refactored.Expression< Double, Float >, refactored.Expression< Double, Float > >(ex1, OPERATION.MINUS, ex2);
}

The Line 3 doesn't compile, it says:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
The constructor Expression<Expression<Double,Float>,Expression<Double,Float>>(Expression<capture#1-of ?,capture#2-of ?>, OPERATION, Expression<capture#3-of ?,capture#4-of ?>) is undefined
Bound mismatch: The type Expression<Double,Float> is not a valid substitute for the bounded parameter <E extends Number> of the type Expression<E,V>
Bound mismatch: The type Expression<Double,Float> is not a valid substitute for the bounded parameter <V extends Number> of the type Expression<E,V>

What's wrong with it?

Expression does not extend number so it is not a legal type parameter.

edit - to address the comment
I am not sure why you need the generic solution for this...
you can have something like

interface Expression {
  Number compute();
}

class AtomicExpression implements Expression {
  private final Number number;
  AtomicExpression(Number number) {
    this.number = number;
  }
  public Number compute() {
    return number;
  }
}

class BinaryExpression implements Expression {
  private final Expression expr1;
  private final Expression expr2;
  private final Operator op;
  AtomicExpression(Expression expr1, Expression expr1. Operator op) {
    this.expr1 = expr1;
    this.expr2 = expr2;
    this.op = op;
  }
  public Number compute() {
    return op(expr1.compute(), expr2.compute());
  }
}

refactored.Expression< ?, ? > ex3 = new refactored.Expression < Double, Float>(ex1, OPERATION.MINUS, ex2);

This should work.

It is obvious from errors you're getting that Expression<?, ?> is not a subclass of Number. If you really want to accept Expression in your constructor then you need to remove the upper bonded parameter (Number) from generics.

Something like this should work for you:

public class Expression <E, V> {
    public Expression(E lV, OPERATION operation, V rV) {}
    public Expression(Expression< E, V > lE, OPERATION operation, Expression< E, V > rE) {}
}

Update: This should work then:

Expression< Double, Float > ex1 = new Expression< Double, Float >(10d, OPERATION.PLUS, 10f);

Expression< Double, Float > ex2 = new Expression< Double, Float >(-3d, OPERATION.MUL, 1f);

Expression< ?, ? > ex3 = new Expression
 < Expression< Double, Float >, Expression< Double, Float > >(ex1, OPERATION.MINUS, ex2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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