泛型和类型安全:检查参数的动态绑定

时间:2016-05-15 16:15:17

标签: java generics parameter-passing type-safety dynamic-binding

我试图找出如何使用泛型来检查来自超类的给定对象是否是来自此超类的子类的子类之一的所需对象。让我举个例子:

我们说我们有这种层次结构:

public interface Expression{
    public Object evaluate();
}

public abstract class BooleanExpression implements Expression{
    public abstract Boolean evaluate();
}

public abstract class PositionExpression implements Expression{
    public abstract Integer[] evaluate();
}

public class Conjunction extends BooleanExpression{
    public Boolean evaluate()
}

public class BooleanTrue extends BooleanExpression{
    @Override
    public Boolean evaluate(){
         return true;
    }
 }

现在我的观点是程序应该只能从Conjunction构造一个对象,当且仅当构造函数中的给定参数是BooleanExpression或此类的子类时。

我尝试过使用这样的泛型:

public class Conjunction<T extends BooleanExpression> extends BooleanExpression{
   public Conjuction(T left, T right){
        this.left = left;
        this.right = right;
   }

   private T left, right;

   @Override
   public Boolean evaluate(){
       return (left.evaluate() && right.evaluate())
   }

当我想创建一个实例时,我有以下代码:

public Expression createConjunction(Expression left, Expression right){
     return new Conjunction<BooleanExpression>(left, right)
}

但不幸的是,这并没有编译!我想使用泛型来检查leftrightBooleanExpression的实例,因为Conjunction只能在两个布尔值之间(而不是PositionExpression })。 但是,leftright可以不同BooleanExpressionleft可以是Conjunction,而right可以是BooleanTrue(例如)。

所以回顾一下:当希望参数Conjunctionleft都是BooleanExpression的子类时,我希望能够创建right的实例。 创建一个Conjuction实例,其中一个参数是PositionExpression的子类,编译器不应该接受它。

我想在不改变createConjunction方法和使用泛型类/接口的情况下解决这个问题。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

public Expression createConjunction(Expression left, Expression right){
     return new Conjunction<BooleanExpression>(left, right)
}

在上面的方法中,您正在请求2 expression个对象,但是在 conjuction构造函数,它正在请求扩展Booleanexpressions的2个对象,这是您遇到编译错误的部分。

您可以将createConjuction方法更改为

 public Expression createConjunction(BooleanExpression left, BooleanExpression right){
         return new Conjunction<BooleanExpression>(left, right)
    }

或者您可以将generic课程中的conjuction表达式更改为

 Conjunction<T extends Expression> extends BooleanExpression{}

答案 1 :(得分:0)

如果你想保留createConjunction方法的签名并且不想更改Conjunction类,那么你可以在createConjunction方法中检查和转换参数的类型。

public Expression createConjunction(Expression left, Expression right){
    if( !(left instanceof BooleanExpression) || !(right instanceof BooleanExpression)){
        throw new IllegalArgumentException("wrong expression arguments, BooleanExpression expected");
    }
    BooleanExpression _left = (BooleanExpression)left;
    BooleanExpression _right = (BooleanExpression)right;
    return new Conjunction<BooleanExpression>(_left, _right);
}