class 和单个 if 语句中的 ANDING 布尔表达式的意外输出
Unexpected output on a ANDING boolean expression in a class and a single if statement
我写了一个从数组中获取数据的函数。该功能的一部分是数据验证,它检查键是否为空以及数组键是否不存在(编辑后我的错误)。该函数如下所示:
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 原理后,通过将 'verification' 放入另一个 class,它看起来像这样:
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
函数之前,使其检查条件是否为假。
布尔表达式不一样,结果不一样,这是怎么回事?
你写了"A part in that function is verification of the data, it checks if the key is NOT empty and if the array key exists.",所以你应该这样做:
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 Exception handling and since you're confusing boolean logig, De Morgan's laws。
!A && !B
与 !(A && B)
不同。只需要查看一个变量为真(让我们选择 A)而另一个为假的情况:
!true && !false --> false && true --> false
!(true && false) --> !(false) --> true
然而,!A && !B
是等同于!(A || B)
:
!(true || false) --> !(true) --> false
这两行不一样:
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
.
中的 &&
不太一样
函数体 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()
方法中会导致上面公开的代码。
我写了一个从数组中获取数据的函数。该功能的一部分是数据验证,它检查键是否为空以及数组键是否不存在(编辑后我的错误)。该函数如下所示:
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 原理后,通过将 'verification' 放入另一个 class,它看起来像这样:
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
函数之前,使其检查条件是否为假。
布尔表达式不一样,结果不一样,这是怎么回事?
你写了"A part in that function is verification of the data, it checks if the key is NOT empty and if the array key exists.",所以你应该这样做:
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 Exception handling and since you're confusing boolean logig, De Morgan's laws。
!A && !B
与 !(A && B)
不同。只需要查看一个变量为真(让我们选择 A)而另一个为假的情况:
!true && !false --> false && true --> false
!(true && false) --> !(false) --> true
然而,!A && !B
是等同于!(A || B)
:
!(true || false) --> !(true) --> false
这两行不一样:
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
.
&&
不太一样
函数体 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()
方法中会导致上面公开的代码。