Résumé : Cet article discutera du concept de polymorphisme et de son application dans la conception orientée objet. Il analysera également comment utiliser le polymorphisme en PHP 5 ainsi que ses avantages et inconvénients.
La prise en charge de la liaison tardive a été implémentée dans les versions récentes de PHP. Bien entendu, de nombreux problèmes subsistent lors de l’utilisation de sa fonction de liaison tardive. Si vous utilisez une ancienne version de PHP (mon serveur exécute PHP 5.0.1), vous constaterez peut-être que la prise en charge de la liaison tardive fait défaut. Par conséquent, veuillez noter que le code de cet article peut ne pas fonctionner dans votre version spécifique de PHP 5.
1. PHP 5 et polymorphisme
Cet article souhaite discuter de l'une des parties les plus importantes de la programmation orientée objet : la conception du polymorphisme. Pour illustrer le problème, j'utilise PHP 5. Avant de continuer la lecture, veuillez préciser que cet article ne concerne pas entièrement PHP. Bien que le langage ait fait de grands progrès en matière de développement rapide au cours des deux dernières versions majeures, sa prise en charge des objets a encore du temps à parcourir avant de pouvoir rivaliser avec des langages plus matures comme le C++ ou Java.
Si vous débutez en programmation orientée objet, cet article n'est peut-être pas adapté pour vous, car cette partie du polymorphisme est particulière : une fois que vous l'aurez comprise, vous ne l'oublierez plus. Si vous souhaitez en apprendre un peu plus sur la programmation et la conception d'objets, et que vous ne savez pas vraiment ce que cela signifie lorsque quelqu'un dit "un objet est polymorphe", alors cet article est fait pour vous.
À la fin de cet article, vous devriez savoir ce qu'est le polymorphisme et comment l'appliquer à la conception orientée objet, et vous comprendrez les avantages et les inconvénients de la programmation objet en PHP 5.
2. Qu'est-ce que le polymorphisme ?
La définition du polymorphisme de Dictionary.com est "se présentant sous différentes formes, étapes ou types dans des organisations indépendantes ou dans la même organisation sans différence fondamentale". objet à travers plusieurs états ou phases. En fait, sa véritable signification est que dans le développement réel, nous devons uniquement nous concentrer sur la programmation d'une interface ou d'une classe de base, et n'avons pas à nous soucier de la classe (classe) spécifique à laquelle appartient un objet.
Si vous êtes familier avec les modèles de conception, même si vous n’en avez qu’une compréhension préliminaire, alors vous comprendrez ce concept. En fait, le polymorphisme est peut-être le meilleur outil de programmation de conception basée sur des modèles. Cela nous permet d'organiser des objets similaires de manière logique afin que nous n'ayons pas à nous soucier du type spécifique de l'objet lors du codage. De plus, il nous suffit de programmer une interface ou une classe de base souhaitée ; Plus une application est abstraite, plus elle devient flexible – et le polymorphisme est l’un des meilleurs moyens d’abstraire le comportement.
Par exemple, considérons une classe appelée Person. Nous pouvons sous-classer Person avec des classes appelées David, Charles et Alejandro. Person a une méthode abstraite AcceptFeedback() et toutes les sous-classes doivent implémenter cette méthode. Cela signifie que tout code qui utilise une sous-classe de la classe de base Person peut appeler la méthode AcceptFeedback(). Il n'est pas nécessaire de vérifier si l'objet est un David ou un Alejandro, il suffit de savoir qu'il s'agit d'une Personne. Par conséquent, votre code doit uniquement se concentrer sur le « plus petit dénominateur commun » : la classe Person.
La classe Person dans cet exemple pourrait également être créée en tant qu'interface. Bien sûr, il existe quelques différences par rapport à ce qui précède, principalement : une interface ne donne aucun comportement, mais détermine uniquement un ensemble de règles. Une interface Person nécessite "Vous devez prendre en charge la méthode AddFeedback()", tandis qu'une classe Person peut fournir du code par défaut pour la méthode AddFeedback() - votre compréhension de cela peut être "Si vous choisissez de ne pas prendre en charge AddFeedback(), alors Vous devez fournir une implémentation par défaut. « Comment choisir une interface ou une classe de base dépasse le sujet de cet article ; cependant, en général, vous devez implémenter une méthode par défaut via la classe de base. Vous pouvez également utiliser une interface si vous pouvez simplement décrire un ensemble souhaité de fonctionnalités que votre classe implémente.
3. Application de la conception polymorphe
Nous allons continuer à utiliser l'exemple de la classe de base Person, et analysons maintenant une implémentation non polymorphe. Les exemples suivants utilisent différents types d’objets Person – une manière de programmer très insatisfaisante. Notez que la classe Person réelle est omise. Jusqu’à présent, nous nous sommes uniquement préoccupés de la question des appels de code.
<?php
$nom = $_SESSION['nom'];
$maPersonne = Personne::GetPerson($nom);
switch (get_class($maPersonne)){
cas 'David' :
$myPerson->AddFeedback('Excellent article !', 'Un lecteur', date('Ym-d'));
casser;
cas 'Charles' :
$myPerson->feedback[] = array('Un lecteur', 'Excellente édition !');
casser;
cas 'Alejandro' :
$myPerson->Feedback->Append('Javascript génial !');
casser;
défaut :
$maPersonne->AddFeedback('Ouais !');
}
?>
Cet exemple montre des objets avec des comportements différents, et une instruction switch est utilisée pour distinguer différents objets de la classe Person afin d'effectuer leurs opérations correctes respectives. Notez que les commentaires ici sont différents selon les conditions. Cela n'est peut-être pas le cas dans le développement d'applications réelles ; j'illustre simplement les différences qui existent dans les implémentations de classes.
Un exemple ci-dessous utilise le polymorphisme.
<?php
$nom = $_SESSION['nom'];
$maPersonne = Personne::GetPerson($nom);
$myPerson->AddFeedback('Excellent article !', 'SomeReader', date('Ym-d'));
?>
Notez qu'il n'y a pas d'instruction switch ici, et plus important encore, il y a un manque d'informations sur le type d'objet que Person::GetPerson() retournera. Et l'autre Person::AddFeedback() est une méthode polymorphe. Le comportement est entièrement encapsulé par des classes concrètes. N'oubliez pas que, que nous utilisions ici David, Charles ou Alejandro, le code appelant n'a jamais besoin de savoir ce que fait la classe concrète, mais uniquement la classe de base.
Bien que mon exemple ne soit pas parfait, il démontre l’utilisation fondamentale du polymorphisme du point de vue du code appelant. Nous devons maintenant analyser l’implémentation interne de ces classes. L'un des avantages de la dérivation à partir d'une classe de base est que la classe dérivée peut accéder au comportement de la classe parent. Il s'agit souvent de l'implémentation par défaut, mais cela peut également se produire dans les chaînes d'héritage de classe pour créer un comportement plus complexe. Vous trouverez ci-dessous une démonstration simple de cette situation.
<?php
personne de classe{
fonction AddFeedback($commentaire, $sender, $date){
//Ajouter des commentaires à la base de données}
}
la classe David étend Person{
fonction AddFeedback($commentaire, $sender){
parent::AddFeedback($comment, $sender,
date('Am-d'));
}
}
?>
Ici, la méthode Person::AddFeedback est appelée pour la première fois dans l'implémentation de la méthode AddFeedback dans la classe David. Vous remarquerez peut-être qu’il imite la surcharge de méthodes en C++, Java ou C#. Gardez à l’esprit qu’il ne s’agit que d’un exemple simplifié et que le code que vous écrivez dépend entièrement de votre projet réel.
4. Liaison tardive en PHP 5
À mon avis, la liaison tardive est une raison importante pour laquelle Java et C# sont si convaincants. Ils permettent aux méthodes de la classe de base d'appeler des méthodes en utilisant "this" ou $this (même si elles n'existent pas dans la classe de base ou si l'appel d'une méthode dans la classe de base peut être remplacé par une autre version dans la classe héritée). Vous pouvez considérer que les implémentations suivantes sont autorisées en PHP :
<?php
personne de classe{
fonction AddFeedback($messageArray) {
$this->ParseFeedback($messageArray);
//Écrire dans la base de données}
}
la classe David étend Person{
fonction ParseFeedback($messageArray){
//Faire une analyse}
}
?>
N'oubliez pas qu'il n'y a pas de ParseFeedback dans la classe Person. Maintenant, en supposant que vous disposez de cette partie du code d'implémentation (pour les besoins de cet exemple), cela fera que $myPerson sera un objet David :
<?php
$maPersonne = Personne::GetPerson($nom);
$maPersonne->AddFeedback($messageArray);
?>
Une erreur d'analyse s'est produite ! Le message d'erreur général est que la méthode ParseFeedback n'existe pas ou des informations similaires. Parlons de la liaison tardive en PHP 5 ! Ensuite, résumons le concept de liaison tardive.
La liaison tardive signifie que l’appel de méthode n’est lié à l’objet cible qu’au dernier moment. Cela signifie que lorsque la méthode est appelée au moment de l'exécution, ces objets ont déjà un type concret. Dans notre exemple ci-dessus, vous avez appelé David::AddFeedback(), et puisque $this dans David::AddFeedback() fait référence à un objet David, vous pouvez logiquement supposer que la méthode ParseFeedback() existe - mais en fait ce n'est pas le cas. existe car AddFeedback() est défini dans Person et ParseFeedback() est appelé depuis la classe Person.
Malheureusement, il n’existe pas de moyen simple d’éliminer ce comportement dans PHP 5. Cela signifie que vous pourriez être un peu impuissant lorsque vous souhaitez créer une hiérarchie de classes polymorphes flexible.
Je dois préciser que j'ai choisi PHP 5 comme langage d'expression pour cet article tout simplement parce que : ce langage ne réalise pas l'abstraction parfaite du concept objet ! Cela est compréhensible puisque PHP 5 est encore en version bêta. De plus, maintenant que des classes abstraites et des interfaces sont ajoutées au langage, une liaison tardive devrait également être implémentée.
5. Résumé
À ce stade, vous devriez avoir une compréhension de base de ce qu'est le polymorphisme et pourquoi PHP 5 n'est pas parfait pour réaliser le polymorphisme. En général, vous devez savoir comment utiliser un modèle objet polymorphe pour encapsuler un comportement conditionnel. Bien entendu, cela augmente la flexibilité de vos objets et signifie moins de code à implémenter. De plus, vous augmentez la clarté de votre code en encapsulant un comportement qui satisfait certaines conditions (en fonction de l'état de l'objet).