У меня есть состояние
if(exists && !isDirectory || !exists)
{}
как я могу изменить это, чтобы это было более понятно.
exists
и isDirectory
оба правда?
У меня есть состояние
if(exists && !isDirectory || !exists)
{}
как я могу изменить это, чтобы это было более понятно.
exists
и isDirectory
оба правда?
Ответы:
||
коммутативно так
if(!exists || (exists && !isDirectory))
эквивалентно.
Теперь, поскольку существует всегда верно во второй части, ||
вы можете отбросить &&
:
if(!exists || !isDirectory)
Или вы можете пойти дальше и сделать:
if(!(exists && isDirectory))
&&
имеет более высокий приоритет (по крайней мере, в большинстве известных языков - могут быть исключения), чем ||
. Таким образом a && b || c
, эквивалентно, (a && b) || c
но не к a && (b || c)
.
!exists || !isDirectory
это более "понятно", потому что isDirectory
не может быть правдой, если !exists
. Итак, как человек, мы скажем: «если он не существует или он [существует, и он] не является каталогом».
||
является коммутативным, только если используется со значениями без побочных эффектов - если, например, он используется с функциями, некоторые функции могут не вызываться (короткое замыкание) или возвращать другое значение в другом порядке.
В качестве процесса я предлагаю создать таблицу истинности:
e = exists
d = isDirectory
e | d | (e && !d) || !e
--+---+----------------
0 | 0 | 1
0 | 1 | 1
1 | 0 | 1
1 | 1 | 0
Это соответствует NAND
операции , которая просто:
!(exists && isDirectory)
Если вы не помните все свои логические элементы, в Википедии есть хорошая ссылка с таблицами истинности для загрузки .
@Christoffer Hammarström поднял важный вопрос о состоянии isDirectory
привязанности к состоянию exists
. Предполагая, что они ссылаются на одну и ту же ссылку, и что невозможно иметь состояние, когда ссылка не существует и является каталогом, таблицу истинности можно записать следующим образом:
e | d | (e && !d) || !e
--+---+----------------
0 | 0 | 1
0 | 1 | n/a
1 | 0 | 1
1 | 1 | 0
n/a
Используется для обозначения состояния , которое не имеет значения. Приемлемые сокращения могут привести к тому 1
или 0
иному состоянию, что приведет к n/a
.
Имея это в виду, !(exists && isDirectory)
все еще действительное сокращение, в результате чего 1
для !e && d
.
Тем не менее, !isDirectory
будет гораздо проще сократить, в результате чего 0
для !e && d
.
isDirectory
зависит от exists
. Он не может быть как каталогом, так и не существовать.
n/a
в тех местах, где невозможно достичь состояния, и уравнение должно быть соответственно уменьшено.
Для лучшей читаемости я хотел бы извлечь логические условия для методов:
if(fileNameUnused())
{...}
public boolean fileNameUnused() {
return exists && !isDirectory || !exists;
}
Или с лучшим именем метода. Если вы можете правильно назвать этот метод, читателю вашего кода не нужно выяснять, что означает логическое условие.
boolean fileNameUnused = !exists || !isDirectory; if (fileNameUnused) { doSomething(); }
Вы могли бы просто попытаться прибить случай без дела и выручить, если это обнаружится.
while(someCondition) {
if(exists && isDirectory)
continue;
// maybe "break", depends on what you're after.
// the rest of the code
}
или даже
function processFile(someFile)
{
// ...
if(exists && isDirectory)
return false;
// the rest of the code
// ...
}
Вы можете использовать таблицу истинности, как указано. Вторым шагом может быть KV-карта для минимизации количества терминов.
Использование законов булевой алгебры - это еще один подход:
A = существует
B =! IsDirectory
! A =! Существует
&& = *
|| = +
[Править]
Более простое преобразование, потому что операции И и ИЛИ являются взаимно-распределительными:
существует &&! isDirectory || ! Существует
= A * B +! A
= (A +! A) * (B +! A)
= 1 * (B +! A)
= B +! A
[/ Edit]
существует &&! isDirectory || ! Существует
= A * B +! A
= A * B +! A * 1 // Идентичность
= A * B +! A * (B + 1) // Аннулятор
= A * B +! A * B +! A / / Распределение и идентификация
= B * (A +! A) +! A // Распределение
= B * 1 +! A // Дополнение 2
= B +! A // Идентичность
=! IsDirectory || !существует
Или с двойным дополнением (!! x = x):
A * B +! A
= !! (A * B +! A)
=! (! (A * B) * A)
=! ((! A +! B) * A)
=! (! A * A + ! B * A)
=! (0 +! B * A)
=! (! B * A)
= B +! A
=! IsDirectory || !существует
Я не люблю использовать "!" когда в выражении более одного условия. Я добавлю строки кода, чтобы сделать его более читабельным.
doesNotExist = !exists;
isFile = exists && !isDirecotry;
if (isFile || doesNotExist)
{}
Как указывалось ранее, условие может быть уменьшено до:
if (!(exists && isDirectory))
Тем не менее, держу пари, что наличие каталога подразумевает существование. Если это так, мы можем уменьшить условие до:
if (!isDirectory)