2016-06-30 2 views
0

Я испытываю поведение, которое я не понимаю, связанный с этим фрагментом кода. Точнее, я ожидал вызова метода getUniqueCost для случая, когда оператор имеет тип Projection (то есть, когда n.isProjection() является истинным), чтобы вызвать метод, имеющий подписи private double getUniqueCost(final Projection p), вместо того, чтобы иметь подпись private double getUniqueCost(final Node p).Сложное поведение перегрузки

Обратите внимание, что Projection является подклассом узла.

Вот код для двух вышеупомянутых методов:

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

Учитывая, что бросок выполняется до фактического вызова метода (то есть вызов по значению семантики, где параметры оцениваются прежде чем оценивать сам метод), я ожидал, что это будет достаточно, чтобы вызвать наиболее конкретный метод (e принимает параметр типа Projection).

Это было некоторое время, так как я имел взгляд на типе системе Java, мои подозреваемый в том, что все выражении child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n) набираются в Node, из-за левую часть того типа действительно Node.

Кто-нибудь может это подтвердить? Если нет, у вас есть лучшее понимание того, что здесь происходит?

Кроме того, есть ли способ иметь более компактный (элегантный?) Способ написания второй версии кода?

ответ

1

Тип вашего тернарного условного выражения - child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n) - это тип, которому могут назначаться как n.getChildren().iterator().next(), так и ((Projection) n). Поэтому, если один из них равен Node, а другой Projection, при условии, что Projection является подклассом Node, тип выражения равен Node.

Ваш второй фрагмент может быть сокращен немного:

if(child.isJoin()){ 
     return getUniqueCost(child); 
    } else { 
     return getUniqueCost((Projection) n); 
    } 

Кастинг n для Projection достаточно самого начала перегруженный getUniqueCost(final Projection p) метод называется. Вам не нужна промежуточная переменная.

+0

Это то, что я имел в виду для статического ввода выражения, но я как-то ожидал, что во время выполнения динамическая типизация будет немного более утонченной, зная, какая «ветвь» будет принята. Видимо, я ожидал слишком многого. Спасибо также за другой совет, это верно. –

Смежные вопросы