Polymorphisme et PHP
By Geoffrey on Friday 13 October 2006, 12:51 - Coding - Permalink
Ou presque ! Je vois déjà vos têtes ahuries devant un tel titre, et pourtant je ne suis pas fou non, j'ai juste décidé d'avoir un titre qui ment par ommission :-) Bref, pour ceux qui ne savent pas ce qu'est le polymorphisme, c'est tout simplement le fait d'avoir plusieurs fonctions qui portent le même nom, mais dont les arguments différent, et pour ceux qui ne comprennet pas pourquoi Polymorphisme et PHP est un drole de titre, et bien sachez que le PHP est un langage non typé (ou faiblement typé selon la personne a qui vous parlez), et qu'il n'est donc pas possible de faire usage du Type Hinting dans la définition d'une fonction (pas sur les types de base en tout cas, mais PHP5.x introduit le type hinting sur les objets, ce qui ne change rien a notre histoire), ce qui fait que PHP ne peut pas gérer le polymorphisme brut.
Cela dit, il est toujours possible de feinter, et on peut simuler le polymorphisme en PHP. Sans plus attendre, voilà un exemple:
function doSomething($arg) {
switch(gettype($arg)) {
case 'integer':
return _doSometing_Integer($arg);
break;
case 'array':
return _doSomething_Array($arg);
break;
default:
return _doSometing_String((string) $arg);
break;
}
}
Voilà. C'est très basique, mais l'idée est là. Un petit tour sur le manuel PHP nous indique qu'utiliser gettype n'est pas très recommandé, nous allons donc procéder autrement (et passer en objet par la même occasion):
class Polymorph {
public function doSometing($arg) {
switch(true) {
case is_array($arg):
return $this->_doSomething_Array($arg);
break;
}
}
private function _doSomething_Array($arg) {
}
}
On aurait également pu faire, pour plus de souplesse (mais avec gettype):
class Polymorph {
public function doSomething($arg) {
$method = '_doSomething_.'.ucfirst(gettype($arg));
if (method_exists($this, $method)) {
call_user_func(array($this, $method), $arg);
} else {
// default comportement
}
}
}
Comments
Je blogmarks.
(le tag rigolo : ^^)
ça faisait longtemps que j'avais pas été blogmarké tiens :)
tiens Thanh, l'ip avec laquelle tu as posté ce commentaire semble etre bloqué par blacklistée par sbl-xbl.spamhaus.org (c'est ce que me dis spamplemousse en tout cas)
Ah bin ça alors ! C'est sympa cette technique ! Comme d'hab, je garde ça sous le coude... :o)
Par contre, je pense qu'on peut encore améliorer le système en utilisant la fonction magique __call($name, $arguments).
On remplace ta fonction doSomething par __call() et en analysant le ou les arguments (qui peuvent être "polymorphés") du tableau $arguments, on choisit la bonne fonction à exécuter...
Bon, du coup, on fait du polymorphisme ET de la surcharge mais bon, ça peut être intéressant, non ?
Z'en pensez quoi ?
j'en pense que t'es encore plus irrécupérable que moi :-)
N'importe quoi, révise tes cours!!!!
Tu mélange entre la surcharge et le polymorphisme.
"Strachey chose the term ad-hoc polymorphism to refer to polymorphic functions which can be applied to arguments of different types, but which behave differently depending on the type of the argument to which they are applied (also known as function overloading)."
http://en.wikipedia.org/wiki/Polymo...
kthx
ps: je n'ai jamais suivi de cours de programmation
c temps de suivre un ....
un cours de français tu veux dire ?
Je suis de l'avis de Toufik, il s'agit de surcharge de méthode. Le polymorphisme ne peut pas exister en PHP : il n'est pas possible de déclarer un pointeur de classe abstraite (ou virtuelle) comme en C++. C'est un raccourci qui porte à confusion, souvent usé et abusé par les programmeurs Java entre autres :)
"déclarer un pointeur de classe abstraite (ou virtuelle)" est, à mon humble avis, une méthode proposé par C pour faire du polymorphisme (j'en sais rien, je connais pas C et n'ai pas envie de le connaître). En revanche, le polymorphisme et la surcharge sont 2 choses différentes:
- la surchage est le fait de créé dans une classe fille une méthode du même nom qu'une méthode d'une classe mère.
- le polymorphisme est le procédé qui permet d'avoir plusieurs fonction du même nom mais avec un nombre de paramètres différents (ou de type différents).
L'exemple de geoffrey est bel bien un code qui compense l'absence du polymorphisme en php.
Greg> "Le polymorphisme ne peut pas exister en PHP"
moi> "ce qui fait que PHP ne peut pas gérer le polymorphisme"
on est donc bien d'accords non ?
n'oubliez pas que ce billet est tagué "BIDOUILLE" et "RIGOLO" (bon ok après ça dépend du sens de l'humour de chacun)
@ Geoffrey :
mon message réagissait au mélange des termes polymorphisme et surcharge. J'avoue que mon message est très réducteur, le polymorphisme est en partie possible en PHP.
@KPADJIK :
"est, à mon humble avis, une méthode proposé par C pour faire du polymorphisme (j'en sais rien, je connais pas C et n'ai pas envie de le connaître)."
Voir ce que sait faire le voisin (le C++ en l'occurence) n'est pas un mal, bien au contraire, tu y apprendras très certainement de nouvelles méhodologies.
Et pour te répondre sur un plan plus théorique, la surcharge de méthode existe bel et bien, comme la surcharge de fonction et ne se restreint pas à une réécriture bête et méchante de la méthode de la classe mère. En C++, comme en java, il est possible de créer dans une même classe plusieures méthodes du même nom, mais avec un prototype différent (et optionnellement des paramètres template pour le C++, mais c'est un autre débat...).
Le polymorphisme est un cas particulier de la surcharge de classes, utile par exemple dans les couches d'abstraction.
Bon donc, pour résumer, si j'ai bien compris:
le polymorphisme est un cas de particulier de la surcharge dans lequel une même méthode (du point de vue de l'utilisateur) se comporte différement en fonction du type des arguments fournis en entrée.
on est bien d'accords ?
Non, ce que tu décris, c'est de la surcharge
Le polymorphisme est le fait d'utiliser un pointeur d'une classe de base pour traiter des instances de classes dérivées.
J'ajouterais que pour que le polymorphisme puisse fonctionner, il faut déclarer (éventuellement en tant que méthode virtuelle/abstraite) dans la classe de base toutes les méthodes que chacune des classes dérivées devront (ré)implémenter
Plutôt d'accord avec Greg dans le fond...
Cependant :
> J'ajouterais que pour que le polymorphisme puisse fonctionner, il faut
> déclarer (éventuellement en tant que méthode virtuelle/abstraite) dans la
> classe de base toutes les méthodes que chacune des classes dérivées
> devront (ré)implémenter
Cela dépend du contexte d'utilisation...
De souvenir, c'est en effet obligatoire si on souhaite travailler avec les types les plus 'bas' de l'echelle (interet premier du polymorphisme, on est d'accord) (ex : on appelle une fonction 'avance' sur un objet 'vehicule'. On est obligé de définir la fonction avance sur vehicule, même si on la redéclare au niveau de nos classes filles 'voiture', et 'bateau'... mais si on appelle directement avance sur un objet voiture, ou un objet bateau, pas la peine de la déclarer sur 'vehicule')(très peu d'interêt, on est d'accord).
Enfin bref, c'est une vaste question et je conseille à ceux que ça interesse de prendre un bon manuel et de travailler dans un language qui gère ces procédés (genre C++ au hasard) avant de s'attaquer à des tweaks pour essayer de reproduire ces mécanismes haut niveau en PHP...
En tout cas bon article, et merci pour toutes ces explications !