Ho alcuni metodi "setter" tra le classi e per comodità ho aggiunto un parametro opzionale $previous
, che accetta un argomento per riferimento e lo popola con il valore esistente prima di sostituirlo con il nuovo uno. Ad esempio:Test degli argomenti opzionali in PHP
public function set_value($key, $value, &$previous = null)
{
$previous = $this->get_value($key);
$this->_values[$key] = $value;
return $this;
}
Questo funziona correttamente; tuttavia, in alcune circostanze, il corrispondente metodo "getter" è un processo un po 'intenso, e il suo funzionamento incondizionato è uno spreco. Ho pensato che avrei potuto provare:
if(null !== $previous)
{
$previous = $this->get_value($key);
}
Questo non funziona, però, come spesso la variabile passata come argomento per $previous
non è stata definita in precedenza nel suo campo di applicazione, e il default è null comunque. L'unica soluzione Ho messo fuori è:
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;
}
O, per una sola riga è:
if(array_key_exists(2, func_get_args()))
{
// ...
}
non mi piace il corpo del metodo essendo affidamento sugli indici di argomenti (quando sembra che non dovrebbe essere necessario) Esiste un modo più pulito per ottenere ciò che sto cercando qui?
ho provato:
if(isset($previous)){}
if(!empty($previous)){}
if(null !== $previous){}
Né lavoro.
Possibili soluzioni così lontane:
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 - Quindi, qualcosa nella zona di:
define('_NOPARAM', '_NOPARAM' . hash('sha4096', microtime()));
function foo($bar = _NOPARAM)
{
// ...
}
@hoppa - Caso d'uso:
$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()
-> ...
Invece di:
$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();
-> ...
non potresti definire il valore predefinito per '$ previous' come' FALSE (o qualche valore del " errato "tipo) - allora si sa che è' nullo' è stato passato, ma è 'FALSE' (o qualsiasi altra cosa) non lo era. Anche questo metodo presenta dei buchi (l'utente potrebbe passare il valore predefinito) ma penso che sarebbe un approccio decente, specialmente se si imposta il valore predefinito una stringa casuale lunga che è altamente improbabile che si trovi nella variabile che è stata passata . – DaveRandom
@DaveRandom - Il valore precedente potrebbe essere un 'falso' booleano in alcune circostanze. Ho scelto "null" per il suo intento semantico, "assenza di valore". – Dan
Vedere il commento modificato sulla stringa lunga casuale - Ammetto che non è un approccio bello o perfetto, ma è un approccio al 99.99999% ... – DaveRandom