скорость: проверка булевых свойств с тремя состояниями

Как разветвить три разных случая в зависимости от всех трех состояний, которые может иметь логическое свойство? Код Java для этого выглядит просто:

public class Foo {
  public Boolean getBool() { return null /* this would be dynamic in RL */; }
}

//  somewhere in the servlet code:
    if (foo.getBool() == null) {
      resp.getWriter().print("not yet set");
    } else if (foo.getBool()) {
      resp.getWriter().print("set to TRUE");
    } else {
      resp.getWriter().print("set to FALSE");
    }

Кажется, что Velocity терпит здесь эпический провал, поскольку в спецификации нет литерала null, а проверки на равенство boolean/not-null несколько взаимозаменяемы ради простоты. Конечно, есть два решения, чтобы избежать этой дилеммы (см. ниже), но есть ли какой-нибудь простой/более чистый способ?

  1. просто добавьте дополнительный геттер в класс Foo, например:

    boolean isBoolSet() {return getBool() != null; }

и тогда код VTL будет таким:

#if(!$foo.boolSet)
  not yet set  
#else
  #if($foo.bool)
    set to TRUE
  #else
    set to FALSE  
  #end
#end
  1. получить какое-то нулевое значение, например,

    Объект getTheNull() {return null; }

и тогда VTL будет выглядеть так:

#if($foo.bool == $foo.theNull)
  not yet set  
#else
  #if($foo.bool)
    set to TRUE
  #else
    set to FALSE  
  #end
#end

person Anton Kraievyi    schedule 09.12.2010    source источник
comment
Что ж, я думаю, что это было бы менее эффективно по скорости, но в конечном итоге было бы намного безопаснее и чище использовать тип enum...   -  person Luis Miguel Serrano    schedule 10.12.2010
comment
В каком смысле это будет менее эффективно? Почти наверняка эффективнее.   -  person Bill K    schedule 10.12.2010
comment
Ну, я знаю, что использование типов enum не рекомендуется, например, на таких платформах, как Android, потому что это медленнее, чем опции с прямым числовым значением. Я не уверен в разнице в скорости между ними в обычной среде Java, но, возможно, она похожа, хотя разница в конечном итоге не так значительна.   -  person Luis Miguel Serrano    schedule 10.12.2010


Ответы (4)


Если вы используете современную версию Velocity, вы можете просто использовать $null или $anyReferenceThatHasNoValue. Вы также можете использовать #elseif для упрощения:

#if($foo.bool == $null)
  not yet set  
#elseif($foo.bool)
    set to TRUE
#else
    set to FALSE
#end

А если серьезно, то это хак, как ни крути. Вы должны использовать перечисление.

person Nathan Bubna    schedule 10.12.2010
comment
о, хорошо, я сам указал, как работать со старой версией - person Anton Kraievyi; 11.12.2010

Каждый раз, когда я пытался впихнуть что-то туда, где оно не подходило, я всегда заканчивал тем, что сожалел, что не просто перешел в более подходящее состояние.

Дайте себе перечисление, тогда вы можете явно сказать, что оно NOT_READY. Явное — это хорошо. Несколько дополнительных строк кода над комментариями — это круто.

Другой пример: если вы когда-нибудь задумывались о создании нового класса или добавлении дополнительного кода в существующий класс, вам, вероятно, понадобится 2 или 3 новых класса.

Просто иди и сделай это.

person Bill K    schedule 09.12.2010

!$foo.bool && $foo.bool != false

эквивалентно

$foo.bool == $null (in Velocity 1.6 onwards)

Я предполагаю, что все дело в ночном программировании и несколько устаревшем/минималистичном руководстве пользователя Velocity...

person Anton Kraievyi    schedule 09.12.2010
comment
вы наверное хотели сказать !$foo.bool && ... - person serg; 10.12.2010
comment
Руководство пользователя Velocity определенно нуждается в обновлении. - person Nathan Bubna; 10.12.2010

Почему вы не инициализируете свое логическое значение внутри конструктора? Таким образом, он никогда не будет нулевым

person Eric    schedule 09.12.2010
comment
поле имеет ›››три‹‹‹ значимых состояния (например, в ожидании/одобрено/отклонено), это, конечно, не очень вписывается в логическое значение, но... - person Anton Kraievyi; 11.12.2010