Php 类中的ANDING布尔表达式和单个if语句的意外输出
我编写了一个从数组中获取数据的函数。该函数的一部分是验证数据,它检查键是否为空以及数组键是否不存在(编辑后的my bad)。函数如下所示:Php 类中的ANDING布尔表达式和单个if语句的意外输出,php,oop,single-responsibility-principle,Php,Oop,Single Responsibility Principle,我编写了一个从数组中获取数据的函数。该函数的一部分是验证数据,它检查键是否为空以及数组键是否不存在(编辑后的my bad)。函数如下所示: public function getData($key = "") { if (!empty($key) && !array_key_exists($key, $this->data)) { throw new ConfigurationException("$key does not exist");
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];
}
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];
}
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];
}
在应用SRP原则之后,通过将“验证”放入另一个类,它看起来是这样的:
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];
}
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];
}
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];
}
从这两个代码片段中,我期望得到相同的结果,因为我将在isPresent
函数之前的code>运算符,使其检查条件是否为false
为什么布尔表达式不一样,结果也不一样?您写道“该函数中的一部分是数据验证,它检查键是否为空以及数组键是否存在”。因此,您应该执行以下操作:
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
之后的代码!这里,您缺少一个代码>在清空()之前
结尾应该是这样的:
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];
}
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];
}
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];
}
阅读后,由于您混淆了布尔逻辑,您写道“该函数中的一部分是数据验证,它检查键是否为空以及数组键是否存在”,因此您应该执行以下操作:
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
之后的代码!这里,您缺少一个代码>在清空()之前
结尾应该是这样的:
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];
}
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];
}
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];
}
请阅读,因为您混淆了布尔逻辑,。!A&&!B
与不同!(A和B)
。我们只需看看一个变量为真(让我们选择A)而另一个变量为假的情况:
!true && !false --> false && true --> false
!(true && false) --> !(false) --> true
然而,!A&&!B
相当于!(A | | B)
:
!A&&!B
与不同!(A和B)
。我们只需看看一个变量为真(让我们选择A)而另一个变量为假的情况:
!true && !false --> false && true --> false
!(true && false) --> !(false) --> true
然而,!A&&!B
相当于!(A | | B)
:
这两行不一样:
if (!empty($key) && !array_key_exists($key, $this->data)) {
return empty($key) && array_key_exists($key, $data);
德摩根的:
!(P && Q) -> (!P) || (!Q)
由于您的返回值
版本在调用点被否定,因此您正在有效地执行!P | | |!Q版本,与中的&&
不完全相同,如果这两行不相同:
if (!empty($key) && !array_key_exists($key, $this->data)) {
return empty($key) && array_key_exists($key, $data);
德摩根的:
!(P && Q) -> (!P) || (!Q)
由于您的返回值
版本在调用点被否定,因此您正在有效地执行!P | | |!Q版本,它与中的&&
不完全相同,如果函数体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()
方法中,将导致上面显示的代码。函数体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()
方法中会导致上面显示的代码。如果您将此与实际问题关联,您可能会获得向上投票,而不是忽略或向下投票@RiggsFolly实际的问题是“为什么布尔表达式不一样,结果也不一样?”如果你把这个问题与实际问题联系起来,你可能会得到赞成票,而不是被忽略票或反对票@RiggsFolly实际的问题是“为什么布尔表达式不一样,结果也不一样?”参见De Morgan定律():!(A&B)=(!A)| |(!B)
见德摩根定律():!(A&&B)=(!A)|(!B)
@DownVoter--是否要评论?您更改了getData()
函数的语义。它最初的目的是返回一个值(给定一个非空的有效键)或整个数据数组(当提供一个空字符串作为键时)。您的版本删除了后者。我刚刚注意到我自己的问题中有一个错误,我想说我还必须检查数组键是否也不符合预期。不过,我喜欢这种解释。@axiac我在开始回答时引用了一句与实现不匹配的话,这是我选择依赖的。因为OP显然把De Morgan搞糊涂了,所以解释源代码不是个好主意。我选择了他的描述。@DownVoter--要不要评论?您更改了getData()
函数的语义。它最初的目的是返回一个值(给定一个非空的有效键)或整个数据数组(当提供一个空字符串作为键时)。您的版本删除了后者。我刚刚注意到我自己的问题中有一个错误,我想说我还必须检查数组键是否也不符合预期。不过,我喜欢这种解释。@axiac我在开始回答时引用了一句与实现不匹配的话,这是我选择依赖的。因为OP显然把De Morgan搞糊涂了,所以解释源代码不是个好主意。我选择了他的描述。