我试图找出如何使用泛型来检查来自超类的给定对象是否是来自此超类的子类的子类之一的所需对象。让我举个例子:
我们说我们有这种层次结构:
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)
}
但不幸的是,这并没有编译!我想使用泛型来检查left
和right
是BooleanExpression
的实例,因为Conjunction
只能在两个布尔值之间(而不是PositionExpression
})。
但是,left
和right
可以不同BooleanExpression
,left
可以是Conjunction
,而right
可以是BooleanTrue
(例如)。
所以回顾一下:当希望参数Conjunction
和left
都是BooleanExpression的子类时,我希望能够创建right
的实例。
创建一个Conjuction
实例,其中一个参数是PositionExpression
的子类,编译器不应该接受它。
我想在不改变createConjunction
方法和使用泛型类/接口的情况下解决这个问题。有什么想法吗?
答案 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);
}