Examiner le polymorphisme en profondeur
Lorsque j’ai commencé cette série, j’ai parlé des quatre piliers de la programmation orientée objet. Chacun de ces sujets est répertorié et lié ci-dessous.
À ce stade, je voudrais normalement commencer à passer au sujet suivant. Avant de le faire, cependant, j’aimerais passer un article de plus à explorer le concept de polymorphisme.
Dans ma carrière, jusqu’à présent, j’ai vu peu de sujets donner à ceux qui se lancent dans la programmation orientée objet plus de confusion et de problèmes que le polymorphisme. J’aimerais donc en discuter un peu plus en profondeur dans le contexte de la programmation orientée objet et en dehors de tout cadre ou application particulier (comme WordPress).
Dans cet article, je ferai un bref examen de ce dont nous avons discuté jusqu’à présent, puis je reviendrai dans le polymorphisme.
Polymorphisme en profondeur
Tout d’abord, comme mentionné, je souhaite passer rapidement en revue ce qui a été discuté jusqu’à présent, surtout si vous avez passé sous silence l’un des messages précédents.
Ne vous inquiétez pas : rien ci-dessous ne digresse dans le code. Au lieu de cela, il définit simplement les termes que nous avons utilisés afin que vous ayez une idée de ce à quoi je fais référence chaque fois que vous voyez le mot apparaître tout au long de cette série.
Abstraction
Nous faisons abstraction de l’idée de quelque chose dans une classe. Au lieu de cela, nous allons extraire des idées dans leurs classes. Et il y a une idée clé ici: une classe doit représenter un nom.
Encapsulation
L’encapsulation n’est vraiment qu’un «grand» mot qui fait référence à l’idée de gérer ses responsabilités (ou de garder une trace de ses données).
Héritage
L’héritage fait référence à l’idée qu’une classe, bien qu’elle ait sa propre implémentation, hérite littéralement des propriétés, des fonctions et de l’implémentation générale d’une classe parent.
Polymorphisme
Le polymorphisme nous permet de faire référence à une classe d’un type lorsqu’elle peut être déclarée comme un autre type.
Cela dit, c’est là que je pense que les choses peuvent devenir un peu plus compliquées. Dans les articles précédents, j’ai fourni un certain nombre d’exemples de code différents (et je vous invite à les consulter).
Mais dans le post d’aujourd’hui, je vais essayer d’explorer l’idée un peu plus loin à la fois dans l’explication puis dans le code.
Relatif à l’héritage
Si ce n’est pas évident à ce stade, le polymorphisme est fortement lié à l’héritage. Pensez-y de cette façon : si une classe hérite des propriétés et des méthodes d’une autre classe, elle peut alors "remplacer" la classe parent.
Cela signifie que si vous avez quelque chose comme une classe Content et que vous avez ensuite deux sous-classes, l’une étant un Post et l’autre étant une Page, vous pouvez instancier la classe en utilisant le type de référence Content.t
Mais au moment de l’exécution, il s’agira en fait d’une instance du type Post. Avoir du sens ? Voici un code à titre d’exemple.
Tout d’abord, nous allons commencer par définir une classe Content :
<?php
class Content {
protected $title;
protected $content;
protected $metadata;
public function __construct()
{
$this->title = "Hello World!";
$this->content = "This is a sample piece of content.";
$this->metadata = "<This is the metadata of the post.>";
}
public function getTitle()
{
return $this->title;
}
public function getContent()
{
return $this->content;
}
public function getMetadata()
{
return $this->metadata;
}
}
Il possède les propriétés générales auxquelles vous vous attendez probablement: titre, contenu et métadonnées. Certes, ces propriétés ne sont que des chaînes, mais elles pourraient être des structures de données plus élaborées dans une situation réelle.
Regardons maintenant un Post :
<?php
class Post extends Content {
private $author;
public function __construct() {
parent::__construct();
$this->author = "Tom McFarlin";
}
public function getAuthor()
{
return $this->author;
}
}
Que se passe-t-il alors si vous appelez une méthode sur la classe Post, comme getTitle, qui n’existe pas mais qui existe dans la classe Content? Ensuite, à cause de l’héritage, il recherchera la méthode dans Post, ne la trouvera pas, puis commencera à la rechercher dans Content.
S’il est trouvé, il l’exécutera.
De même, nous pouvons faire quelque chose comme ça avec la classe Page et les données de contenu. Tout d’abord, nous instancions la classe de base puis nous définissons les propriétés spécifiques à la Page. Dans ce cas, ce sera une catégorie.
<?php
class Page extends Content {
private $category;
public function __construct() {
parent::__construct();
$this->category = "Articles";
}
public function getCategory()
{
return $this->category;
}
}
Maintenant, lorsque nous exécutons le code, nous pouvons commencer par le contenu :
<?php
$content = new Content();
echo $content->getTitle();
Notez que cela ressemble à ce à quoi nous nous attendions puisque nous avons un titre et que nous avons du contenu. Regardons aussi le Post :
<?php
// These will work because they reside in the Content base class.
$post = new Post();
echo $post->getAuthor();
echo $post->getTitle();
Cela fonctionne parce que nous avons un auteur mais nous avons aussi un titre car il réside dans Content. Mais si nous essayons d’appeler getAuthor sur une instance de Post?
<?php
// These will work because they reside in the Content base class.
$post = new Post();
echo $post->getAuthor();
echo $post->getTitle();
Nous allons obtenir une erreur car la méthode ne réside pas dans cette classe.
Alors, que devons-nous faire? Comme nous n’avons pas de types forts en PHP, nous ne pouvons pas le convertir en un type différent.
Il existe des modèles de conception pour cela, dont je parlerai dans une prochaine série d’articles, mais PHP ne le permet pas aussi facilement que d’autres langages (comme C# ou Java).
Questions sur le polymorphisme
Espérons que le code ci-dessus vous donne une idée de la façon dont un type concret tel qu’un Post ou une Page peut implicitement avoir les propriétés et les méthodes de sa classe de base, Content, utilisées lors de l’exécution.
Mais cela soulève aussi quelques questions, n’est-ce pas? Par exemple:
- Pourquoi le polymorphisme est-il utile ? En fin de compte, c’est une question de flexibilité. Autrement dit, vous pouvez écrire un type de contenu générique, mais ensuite créer un article ou une page, comme nous l’avons vu ci-dessus. Cela nous donne alors tous les avantages de la classe Content tout en nous donnant également la spécificité de la classe Post par exemple.
- Cela semble être plus déroutant que flexible. D’une certaine manière, c’est déroutant car le code nécessite un peu de traçage. Autrement dit, vous pourriez commencer dans la classe Post et devoir rechercher ce que propose la classe Content . D’un autre côté, il est également très facile d’introduire une nouvelle sous-classe de contenu, puis de l’utiliser lorsqu’elle est la mieux adaptée à l’exécution.
En ce qui concerne les superclasses et les sous-classes, c’est là qu’un IDE solide entre en jeu.
C’est toujours agréable d’avoir un éditeur que vous aimez, bien sûr, mais en avoir un qui peut déterminer intuitivement quelle est la classe parent, quelle est la classe de base, etc., peut grandement aider à tracer, déboguer, suivre et écrire de nouveaux code.
Mais c’est le contenu d’un autre article qui viendra après que nous ayons parlé des modèles de conception.

