Donc, je suis de programmation dans une belle, jusqu'à ce jour, orienté objet de mode. Je fais régulièrement l'utilisation des différents aspects de la programmation orientée objet PHP met en œuvre, mais je me demande quand pourrais-je besoin d'utiliser des fermetures. Les experts là-bas qui peut jeter quelque lumière sur le moment où il serait utile de mettre en œuvre les bouchons?
Réponses
Trop de publicités?PHP va soutenir les fermetures de manière native dans 5.3. Une fermeture est bon lorsque vous souhaitez une fonction locale qui n'est utilisé que pour certains petits, fins spécifiques. Le RFC pour les fermetures de donner un bon exemple:
function replace_spaces ($text) {
$replacement = function ($matches) {
return str_replace ($matches[1], ' ', ' ').' ';
};
return preg_replace_callback ('/( +) /', $replacement, $text);
}
Cela vous permet de définir l' replacement
fonction localement à l'intérieur d' replace_spaces()
, de sorte qu'il n'est pas:
1) d'Encombrer l'espace de noms global
2) Rendre les gens trois ans me demande pourquoi il y a une fonction définie à l'échelle mondiale qui est seulement utilisé à l'intérieur d'une autre fonction
Il garde les choses organisées. Remarquez comment la fonction elle-même n'a pas de nom, elle est tout simplement définies et attribuées comme une référence à l' $replacement
.
Mais n'oubliez pas, vous devez attendre pour PHP 5.3 :)
Lorsque vous aurez besoin d'une fonction à l'avenir, qui effectue une tâche que vous avez décidé sur maintenant.
Par exemple, si vous lisez un fichier de configuration et l'un des paramètres qui vous dit que l' hash_method
pour votre algorithme est - multiply
plutôt que d' square
, vous pouvez créer une fermeture qui va être utilisé partout où vous avez besoin de quelque chose de hachage.
La fermeture peut être créé (par exemple,) config_parser()
; il crée une fonction appelée do_hash_method()
à l'aide de variables locales d' config_parser()
(à partir du fichier de config). Chaque fois qu' do_hash_method()
est appelé, il a accès à des variables locales dans le champ d'application de l'config_parser()
, même si elle n'est pas appelée dans cette portée.
Un espoir bon exemple hypothétique:
function config_parser()
{
// Do some code here
// $hash_method is in config_parser() local scope
$hash_method = 'multiply';
if ($hashing_enabled)
{
function do_hash_method($var)
{
// $hash_method is from the parent's local scope
if ($hash_method == 'multiply')
return $var * $var;
else
return $var ^ $var;
}
}
}
function hashme($val)
{
// do_hash_method still knows about $hash_method
// even though it's not in the local scope anymore
$val = do_hash_method($val)
}
Outre les détails techniques, les fermetures sont un pré-requis fondamental pour un style de programmation connu comme la fonction de programmation orienté. La fermeture est à peu près utilisé pour la même chose que vous utilisez un objet en programmation orientée objet; Il lie des données (variables) avec un peu de code (une fonction), que vous pouvez ensuite passer à quelque part d'autre. En tant que tels, ils ont une incidence sur la façon dont vous écrivez des programmes ou - si vous ne changez pas la façon dont vous écrivez vos programmes - ils n'ont pas d'impact du tout.
Dans le contexte de PHP, ils sont un peu bizarres, étant donné que PHP est déjà lourd sur la classe de base, le paradigme orienté objet, ainsi que l'ancienne procédure. Généralement, les langues qui ont des fermetures, a la pleine portée lexicale. Afin d'assurer la rétrocompatibilité, PHP ne va pas à l'obtenir, ce qui signifie que les fermetures vont être un peu différent ici, que dans d'autres langues. Je pense que nous avons encore à voir exactement comment ils seront utilisés.
J'aime le contexte fourni par troelskn post. Quand je veux faire quelque chose comme Dan Udey l'exemple en PHP, j'utilise le OO Modèle de Stratégie. À mon avis, c'est beaucoup mieux que l'introduction d'une nouvelle fonction globale dont le comportement est déterminé au moment de l'exécution.
http://en.wikipedia.org/wiki/Strategy_pattern
Vous pouvez également appeler des fonctions et des méthodes à l'aide d'une variable contenant le nom de la méthode en PHP, ce qui est excellent. donc, une autre de prendre sur Dan exemple serait quelque chose comme ceci:
class ConfigurableEncoder{
private $algorithm = 'multiply'; //default is multiply
public function encode($x){
return call_user_func(array($this,$this->algorithm),$x);
}
public function multiply($x){
return $x * 5;
}
public function add($x){
return $x + 5;
}
public function setAlgorithm($algName){
switch(strtolower($algName)){
case 'add':
$this->algorithm = 'add';
break;
case 'multiply': //fall through
default: //default is multiply
$this->algorithm = 'multiply';
break;
}
}
}
$raw = 5;
$encoder = new ConfigurableEncoder(); // set to multiply
echo "raw: $raw\n"; // 5
echo "multiply: " . $encoder->encode($raw) . "\n"; // 25
$encoder->setAlgorithm('add');
echo "add: " . $encoder->encode($raw) . "\n"; // 10
bien sûr, si vous voulez qu'il soit disponible partout, vous pourriez juste faire tout statique...
@jean-Boker - ils sont à venir, je crois, en PHP 5.3
Voici un bon lien sur eux, en expliquant certains de leur utilité http://wiki.php.net/rfc/closures