令人困惑的重载行为
Confusing behaviour of overloading
我遇到了一种我无法理解的与此代码片段相关的行为。更准确地说,我期望在运算符类型为 Projection
的情况下调用 getUniqueCost
方法(即,当 n.isProjection()
为真时)调用具有 as 的方法签名 private double getUniqueCost(final Projection p)
而不是签名 private double getUniqueCost(final Node p)
.
注意 Projection 是 Node 的子类。
这里是上述两种方法的代码:
private double getUniqueCost(final Node n){
if(n.isScan())
return getUniqueCost(estimateCardinality(n));
if(n.isJoin())
return getUniqueCost((NJoin) n);
if(n.isUnion())
return getUniqueCost((Union) n);
if(n.isMaterialization())
return getUniqueCost(n.getChildren().iterator().next());
if(n.isProjection()){
return getUniqueCost(child.isJoin() ?
n.getChildren().iterator().next() : ((Projection) n));
}
throw new IllegalArgumentException("Unknown node type: " + n.getOperator());
}
private double getUniqueCost(final Projection p){
return getUniqueCost(estimateCardinality(p)) +
getUniqueCost(p.getChildren().iterator().next());
}
真正调用第二个方法的唯一方法是修改第一个方法如下(省略的代码与之前相同):
private double getUniqueCost(final Node n){
[...]
if(n.isProjection()){
final Node child = n.getChildren().iterator().next();
if(child.isJoin()){
return getUniqueCost(child);
}
final Projection proj = (Projection) n;
return getUniqueCost(proj);
}
throw new IllegalArgumentException("Unknown node type: " + n.getOperator());
}
考虑到转换是在实际调用方法之前执行的(即,按值语义调用,在评估方法本身之前评估参数),我期望它足以调用最具体的方法(接受类型 Projection
的参数)。
自从我查看 Java 的类型系统以来已经有一段时间了,我怀疑整个表达式 child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n)
被键入为 Node
,由于左边部分那些类型确实是 Node
.
有人可以证实吗?如果没有,你对这里发生的事情有更好的了解吗?
另外,有没有办法让第二版代码的写法更简洁(优雅?)?
您的三元条件表达式的类型 - child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n)
- 是 n.getChildren().iterator().next()
和 ((Projection) n)
都可以分配给的类型。因此,如果其中一个是Node
,另一个是Projection
,假设Projection
是Node
的子class,表达式的类型是Node
.
您的第二个片段可以缩短一点:
if(child.isJoin()){
return getUniqueCost(child);
} else {
return getUniqueCost((Projection) n);
}
将 n
转换为 Projection
足以调用重载的 getUniqueCost(final Projection p)
方法。您不需要中间变量。
我遇到了一种我无法理解的与此代码片段相关的行为。更准确地说,我期望在运算符类型为 Projection
的情况下调用 getUniqueCost
方法(即,当 n.isProjection()
为真时)调用具有 as 的方法签名 private double getUniqueCost(final Projection p)
而不是签名 private double getUniqueCost(final Node p)
.
注意 Projection 是 Node 的子类。
这里是上述两种方法的代码:
private double getUniqueCost(final Node n){
if(n.isScan())
return getUniqueCost(estimateCardinality(n));
if(n.isJoin())
return getUniqueCost((NJoin) n);
if(n.isUnion())
return getUniqueCost((Union) n);
if(n.isMaterialization())
return getUniqueCost(n.getChildren().iterator().next());
if(n.isProjection()){
return getUniqueCost(child.isJoin() ?
n.getChildren().iterator().next() : ((Projection) n));
}
throw new IllegalArgumentException("Unknown node type: " + n.getOperator());
}
private double getUniqueCost(final Projection p){
return getUniqueCost(estimateCardinality(p)) +
getUniqueCost(p.getChildren().iterator().next());
}
真正调用第二个方法的唯一方法是修改第一个方法如下(省略的代码与之前相同):
private double getUniqueCost(final Node n){
[...]
if(n.isProjection()){
final Node child = n.getChildren().iterator().next();
if(child.isJoin()){
return getUniqueCost(child);
}
final Projection proj = (Projection) n;
return getUniqueCost(proj);
}
throw new IllegalArgumentException("Unknown node type: " + n.getOperator());
}
考虑到转换是在实际调用方法之前执行的(即,按值语义调用,在评估方法本身之前评估参数),我期望它足以调用最具体的方法(接受类型 Projection
的参数)。
自从我查看 Java 的类型系统以来已经有一段时间了,我怀疑整个表达式 child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n)
被键入为 Node
,由于左边部分那些类型确实是 Node
.
有人可以证实吗?如果没有,你对这里发生的事情有更好的了解吗?
另外,有没有办法让第二版代码的写法更简洁(优雅?)?
您的三元条件表达式的类型 - child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n)
- 是 n.getChildren().iterator().next()
和 ((Projection) n)
都可以分配给的类型。因此,如果其中一个是Node
,另一个是Projection
,假设Projection
是Node
的子class,表达式的类型是Node
.
您的第二个片段可以缩短一点:
if(child.isJoin()){
return getUniqueCost(child);
} else {
return getUniqueCost((Projection) n);
}
将 n
转换为 Projection
足以调用重载的 getUniqueCost(final Projection p)
方法。您不需要中间变量。