Redéfinir les Méthodes de la Classe ou de la Classe
Est-il possible de redéfinir une classe ou certaines de ses méthodes, sans l'aide d'typique de l'héritage? Par exemple:
class third_party_library {
function buggy_function() {
return 'bad result';
}
function other_functions(){
return 'blah';
}
}
Que puis-je faire pour remplacer buggy_function()
? Évidemment, c'est ce que je voudrais faire
class third_party_library redefines third_party_library{
function buggy_function() {
return 'good result';
}
function other_functions(){
return 'blah';
}
}
C'est mon exact dilemme: j'ai mis à jour une bibliothèque tierce qui brise mon code. Je ne veux pas modifier la bibliothèque directement, comme les futures mises à jour pourraient briser à nouveau le code. Je suis à la recherche d'une méthode simple pour remplacer la méthode de classe.
J'ai trouvé cette bibliothèque qui dit qu'il peut le faire, mais je suis méfiant car c'est l'âge de 4 ans.
EDIT:
Je devrais avoir précisé que je ne peux pas renommer la classe de third_party_library
à magical_third_party_library
ou quoi que ce soit d'autre à cause de cadre de limites.
Pour mes fins, serait-il possible de simplement ajouter une fonction à la classe? Je pense que vous pouvez le faire en C# avec quelque chose qui s'appelle une "classe partielle."
- PHP ne supporte pas cela. Vous pouvez étendre la classe et de ré-utiliser. Qui est-il. Désolé.
- Vous pouvez renommer l'original buggy classe? Renommer buggy_third_party, et exend vous-même, de donner à votre classe, le nom d'origine.
Vous devez vous connecter pour publier un commentaire.
Il est appelé monkey patching. Mais, PHP n'a pas de support natif pour elle.
Bien que, comme d'autres l'ont souligné, également, l' runkit bibliothèque est disponible pour ajouter le support de la langue et est le successeur de classkit. Et, bien qu'il semblait avoir été abandonné par son créateur (le fait d'avoir déclaré qu'il n'était pas compatible avec PHP 5.2 et versions ultérieures), le projet ne semblent avoir aujourd'hui une nouvelle maison et responsable.
J'ai encore ne peux pas dire que je suis un fan de son approche. Apporter des modifications apportées par l'évaluation des chaînes de code m'a toujours semblé être potentiellement dangereux et difficile à déboguer.
Encore,
runkit_method_redefine
semble être ce que vous cherchez, et un exemple de son utilisation peuvent être trouvés dans/tests/runkit_method_redefine.phpt
dans le référentiel:runkit semble être une bonne solution, mais n'est pas activé par défaut et certaines parties sont encore expérimentales. J'ai donc bidouillé une petite classe qui remplace des définitions de fonction dans un fichier de classe. Exemple d'utilisation:
Puis d'inclure la classe à modifier et redéfinir ses méthodes:
Ensuite eval le nouveau code:
Un peu brut, mais il fonctionne!
Par souci d'exhaustivité - monkey patching est disponible en PHP par runkit. Pour plus de détails, voir
runkit_method_redefine()
.Comment sur en l'enveloppant dans une autre classe comme
Pour les personnes qui sont toujours à la recherche de cette réponse.
Vous devez utiliser s'étend en combinaison avec les espaces de noms.
comme ceci:
Ensuite pour l'utiliser, il faut procéder comme suit:
Oui, il est appelé
extend
:Je le préfixe "sd". 😉
Gardez à l'esprit que lorsque vous étendez une classe de remplacer les méthodes, la signature de la méthode doit correspondre à l'original. Ainsi par exemple, si l'original dit
buggy_function($foo, $bar)
, il doit correspondre aux paramètres de la classe de l'étendre.PHP est assez détaillé à ce sujet.
Zend Studio et PDT (basé sur eclipse ide) ont une certaine construit dans refractoring outils. Mais il n'y a pas de méthodes pour ce faire.
Aussi vous ne voulez pas avoir de mauvais code dans votre système à tous. Étant donné qu'il pourrait être appelé par erreur.
Si la bibliothèque est explicitement la création de la mauvaise classe, et non pas à l'aide d'une localisation ou un système de dépendance, vous êtes hors de la chance. Il n'existe aucun moyen de remplacer une méthode sur une autre classe, à moins que vous sous-classe.
La solution pourrait être de créer un fichier de correctif qui résout la bibliothèque, de sorte que vous pouvez mettre à niveau la bibliothèque et ré-appliquer le patch correctif de la méthode spécifique.
Vous pourriez être en mesure de le faire avec runkit. http://php.net/runkit
Il y a toujours l'extension de la classe avec une nouvelle, bon, de la méthode et de l'appel de cette classe au lieu de la poussette un.
(Désolé pour la mise en forme de merde)
Vous pouvez faire une copie de la bibliothèque de la classe, avec tout les mêmes, sauf le nom de la classe. Puis remplacer le renommé classe.
Il n'est pas parfait, mais il permet d'améliorer la visibilité de l'extension de la classe des modifications. Si vous chercher à la bibliothèque avec quelque chose comme Compositeur, vous aurez à engager la copie au contrôle de code source et de le mettre à jour lorsque vous mettez à jour la bibliothèque.
Dans mon cas, c'était une vieille version de https://github.com/bshaffer/oauth2-server-php. J'ai modifié la bibliothèque de l'autochargeur de récupérer mon fichier de classe à la place. Mon fichier de classe a eu sur le nom d'origine et l'étendue de la copie de la version de l'un des fichiers.
Depuis que vous avez toujours accès à la base de code en PHP, redéfinir les principales fonctions de classe que vous souhaitez remplacer comme suit, ce qui devrait laisser vos interfaces intacte:
Vous pouvez pour une raison d'utiliser une variable privée, mais alors vous aurez seulement être en mesure d'accéder à la fonction par l'extension de la classe ou de la logique à l'intérieur de la classe. De même, il est possible que vous voudriez avoir différents objets de la même classe ont des fonctions différentes. Si oui, n'utilisez pas statique, mais en général, vous voulez qu'il soit statique afin de ne pas dupliquer l'utilisation de la mémoire pour chaque objet. Le " ranOnce code tout à fait sûr que vous avez seulement besoin de l'initialiser une fois pour la classe, pas pour tous les
$myObject = new third_party_library()
Maintenant, plus tard dans votre code ou d'une autre classe - chaque fois que la logique atteint un point où vous en avez besoin pour remplacer la fonction - il suffit de faire comme suit:
Comme une note de côté, si vous faites tout votre classe fonctionne de cette manière et l'utilisation d'une chaîne de clé/valeur en magasin comme
public static $functions['function_name'] = function(...){...};
cela peut être utile pour la réflexion. Pas autant en PHP comme les autres langues, mais parce que vous pouvez déjà saisir la classe et les noms de fonction, mais vous pouvez économiser de traitement et les futurs utilisateurs de votre classe peut utiliser des remplacements en PHP. Il est, cependant, un niveau supplémentaire d'indirection, je voudrais donc éviter de l'utiliser sur des primitives de classes dans la mesure du possible.