【发布时间】:2016-05-15 16:15:17
【问题描述】:
我一直在试图弄清楚如何使用泛型来检查来自超类的给定对象是否是来自该超类的子类的子类之一的所需对象。举个例子吧:
假设我们有一个这样的层次结构:
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 或此类的子类时,程序才应该能够从 Conjunction 构造对象。
我尝试过使用这样的泛型:
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(例如)。
回顾一下:当给定参数left 和right 都是BooleanExpression 的子类时,我希望能够创建Conjunction 的实例。
编译器不应接受创建 Conjuction 的实例,其中一个参数是 PositionExpression 的子类。
我想在不更改 createConjunction 方法并使用泛型类/接口的情况下解决这个问题。有什么想法吗?
【问题讨论】:
-
您肯定必须更改
createConjunction函数,因为在当前形式下它根本是无效的。您只需要更改left和right的类型即可BooleanExpression而不是Expression。 -
编译器正在做它应该做的事情。它无法编译,因为
left和right是Expressions,但您的Conjuction构造函数明确要求它们是BooleanExpression的子类。 -
@Casey 我猜编译器无法检查
left的底层对象是否属于BooleanExpression的子类,是吗? (例如,当我调用此方法createConjunction时,left参数可能包含BooleanTrue,它是BooleanExpression的子类(实现Expression接口)) -
@luk2302 是的,我希望我不必这样做,因为在我当前的项目中,我不允许这样做。不过还是谢谢你的回答!
-
您在这里面临的问题是编译器 不知道
left和right的实际内容。编译发生在运行时之前。如果对象实际上不包含合适的表达式,那么在运行时该方法会发生什么?返回空?抛出错误?开放的问题太多了。
标签: java generics parameter-passing type-safety dynamic-binding