【发布时间】:2012-01-23 15:27:19
【问题描述】:
我有一些跨类的“setter”方法,为了方便起见,我添加了一个可选参数$previous,它通过引用获取一个参数并用现有值填充它,然后用新值替换它。例如:
public function set_value($key, $value, &$previous = null)
{
$previous = $this->get_value($key);
$this->_values[$key] = $value;
return $this;
}
这很好用;但是在某些情况下,相应的“getter”方法有点过程密集,无条件运行它是一种浪费。我想我可以测试一下:
if(null !== $previous)
{
$previous = $this->get_value($key);
}
这不起作用,因为通常作为$previous 的参数传递的变量之前没有在它的范围内定义,并且无论如何默认为null。我破解的唯一解决方案是:
public function set_value($key, $value, &$previous = null)
{
$args = func_get_args();
if(isset($args[2])
{
$previous = $this->get_value($key);
}
$this->_values[$key] = $value;
return $this;
}
或者,单行:
if(array_key_exists(2, func_get_args()))
{
// ...
}
我不喜欢方法体依赖于参数索引(当它看起来应该是不必要的时候)有没有更简洁的方法来实现我在这里的目标?
我试过了:
if(isset($previous)){}
if(!empty($previous)){}
if(null !== $previous){}
都不行。
到目前为止可能的解决方案:
if(func_num_args() == $num_params){}
if(array_key_exists($param_index, func_get_args())){}
// 5.4
if(isset(func_get_args()[$param_index])){}
// 5.4
if(func_num_args() == (new \ReflectionMethod(__CLASS__, __FUNCTION__))
->getNumberOfParameters()){}
@DaveRandom -- 所以,在以下方面:
define('_NOPARAM', '_NOPARAM' . hash('sha4096', microtime()));
function foo($bar = _NOPARAM)
{
// ...
}
@hoppa -- 用例:
$obj->set_something('some_key', $some_value, $previous) // set
->do_something_that_uses_some_key()
->set_something('some_key', $previous) // and reset
->do_something_that_uses_some_key()
-> ...
代替:
$previous = $obj->get_something('some_key'); // get
$obj->set_something('some_key', $some_value) // set
->do_something_that_uses_some_key();
->set_something($previous) // and reset
->do_something_that_uses_some_key();
-> ...
【问题讨论】:
-
您不能将
$previous的默认值定义为FALSE(或“错误”类型的某个值) - 那么您知道它是null它已通过,但是它不是FALSE(或其他)。此方法也有漏洞(用户可能会传递您的默认值),但我认为这将是一个不错的方法 - 特别是如果您将默认值设为一个长随机字符串,该字符串极不可能出现在传递的变量中. -
@DaveRandom -- 在某些情况下,先前的值可能是布尔值
false。我选择了null,因为它的语义意图是“缺乏价值”。 -
查看关于长随机字符串的编辑评论 - 我承认这不是一个漂亮或完美的方法,但它是一个有效的 99.99999% 方法......
-
@DaveRandom -- 我想我可以定义一些任意字符串作为默认值,但是(非常类似于
md5的参数)仍然存在冲突的可能性。我认为这将是微不足道的,我只是忽略了一些东西。 -
另一个变量
$fetch_previous并明确测试$fetch_previous == true怎么样?返工太多?
标签: php pass-by-reference default-value optional-parameters