Неожиданный вывод логического выражения ANDING в классе и одного оператора if

Я написал функцию для получения данных из массива. Часть этой функции — проверка данных, она проверяет, не является ли ключ пустым и не существует ли ключ массива (мой плохой после редактирования). Функция выглядит так:

public function getData($key = "")
{
if (!empty($key) && !array_key_exists($key, $this->data)) {
throw new ConfigurationException("$key does not exist");
}
return empty($key) ? $this->data : $this->data[$key];
}

После применения принципа SRP путем помещения «проверки» в другой класс это выглядело так:

class ConfigurationVerificationHandler
{

public function isPresent($key, array $data)
{
return empty($key) && array_key_exists($key, $data);
}
}

public function getData($key = "")
{
$verificationHandler = new ConfigurationVerificationHandler();
if (!$verificationHandler->isPresent($key, $this->data)) {
throw new ConfigurationException("$key does not exist");
}
return empty($key) ? $this->data : $this->data[$key];
}

От обоих этих фрагментов я ожидал того же результата, потому что ! оператор перед isPresent функция, проверяя, является ли условие ложным.

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

0

Решение

!A && !B это не то же самое, что !(A && B), Нужно только взглянуть на случай, когда одна переменная равна true (давайте выберем A), а другая — false:

!true && !false --> false && true --> false

!(true && false) --> !(false) --> true

Тем не мение, !A && !B является эквивалентно !(A || B):

!(true || false) --> !(true) --> false
1

Другие решения

Вы написали: «Часть в этой функции — проверка данных, она проверяет, не является ли ключ пустым и существует ли ключ массива», поэтому вы должны сделать это:

public function getData($key = "")
{
// Throw exception if key is empty OR array-key does not exist
if (empty($key) || !array_key_exists($key, $this->data)) {
throw new ConfigurationException("$key does not exist");
}
// This won't be executed if $key is empty or does not exist
return $this->data[$key];
}

Обратите внимание, что, так как вы не поймали свое исключение, код после throw не будет казнен! Здесь вам не хватает ! до empty(),

public function isPresent($key, array $data)
{
return !empty($key) && array_key_exists($key, $data);
}

И конец должен выглядеть так:

public function getData($key = "")
{
$verificationHandler = new ConfigurationVerificationHandler();
if (!$verificationHandler->isPresent($key, $this->data)) {
throw new ConfigurationException("$key does not exist");
}
// $key can't be empty here
return $this->data[$key];
}

Читать Обработка исключений PHP и так как вы путаете логическую логику, Законы де Моргана.

2

Тело функции isPresent() должно быть:

public function isPresent($key, array $data)
{
return empty($key) || array_key_exists($key, $data);
}

Вы начали с:

if (! empty($key) && ! array_key_exists($key, $this->data)) {

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

if (! (empty($key) || array_key_exists($key, $this->data))) {

На следующем шаге, перемещая условие в isPresent() Метод приводит к приведенному выше коду.

0

Эти две строки не совпадают:

if (!empty($key) && !array_key_exists($key, $this->data)) {

return empty($key) && array_key_exists($key, $data);

Де Морган:

 !(P && Q) -> (!P) || (!Q)

Так как ваш return версия отменяется в точке вызова, вы эффективно выполняете! P || ! Q версия, которая не совсем совпадает с вашей && в if,

-1
По вопросам рекламы [email protected]