0

我被困在试图弄清楚如何使用泛型来检查超类的给定对象是否是来自此超类的子类之一的子类的期望对象。让我举一个例子:泛型和类型安全:检查参数的动态绑定

比方说,我们有一个层次结构:

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

现在,我的观点是,该计划应只能够当且仅当在给定的参数来构造一个对象从连词该构造函数是一个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) 
} 

但不幸的是,这并不编译!我想使用泛型来检查leftright是否为BooleanExpression的实例,因为Conjunction只能在两个布尔值之间(而不是PositionExpression)。 然而,leftright可以是不同的BooleanExpressionleft可以是Conjunctionright可以是BooleanTrue(作为示例)。

所以,我想要创建一个Conjunction的实例,当两个给定的参数leftright都是BooleanExpression的子类时。 创建一个Conjuction的实例,其中一个参数是PositionExpression的子类不应被编译器接受。

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

+0

你一定要改变'createConjunction'函数,因为在它的当前形式下它是无效的。所有你应该改变的是使'左'和'右'布尔表达式'而不是'表达式'的类型。 – luk2302

+0

编译器正在做它应该做的事情。它不会编译,因为'left'和'right'是'Expression's,但是'Conjuction'构造函数明确要求它们是'BooleanExpression'的子类。 – Casey

+0

@Casey我猜编译器没有办法检查'left'的底层对象是否是子类'BooleanExpression',是吗? (例如,当我调用这个方法'createConjunction'时,'left'参数可以包含'BooleanTrue',它是'BooleanExpression'的子类(它实现'Expression'接口)) –

回答

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

,或者你可以在conjuction类改变generic表达

Conjunction<T extends Expression> extends BooleanExpression{} 
0

如果你想保持createConjunction方法和Don”的签名我想要改变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); 
}