{"id":230112,"date":"2022-11-22T11:32:00","date_gmt":"2022-11-22T08:32:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230112"},"modified":"2022-11-22T11:32:14","modified_gmt":"2022-11-22T08:32:14","slug":"classes-abstraites-partie-1-comportement-dabstraction","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fr\/classes-abstraites-partie-1-comportement-dabstraction\/","title":{"rendered":"Classes abstraites, partie 1 &#8211; Comportement d&rsquo;abstraction"},"content":{"rendered":"\n<p>Il y a environ un mois, <a href=\"https:\/\/wordpress.mediadoma.com\/fr\/les-deux-premiers-piliers-de-la-poo\/\" title=\"j'ai \u00e9crit sur l'un\">j&rsquo;ai \u00e9crit sur l&rsquo;un<\/a> des piliers de la programmation orient\u00e9e objet (en particulier l&rsquo;abstraction). Dans l&rsquo;article, j&rsquo;ai d\u00e9fini l&rsquo;abstraction comme suit\u00a0:<\/p>\n<blockquote>\n<p>Au lieu de cela, nous allons extraire des id\u00e9es dans leurs classes. Et il y a une id\u00e9e cl\u00e9 ici: une classe doit repr\u00e9senter un nom.<\/p>\n<\/blockquote>\n<p>Et bien que ce soit toujours vrai, l&rsquo;id\u00e9e de <strong>classes abstraites<\/strong> est quelque chose de diff\u00e9rent dans la programmation orient\u00e9e objet.<\/p>\n<p>Cela semble d\u00e9routant, non\u00a0? C&rsquo;est-\u00e0-dire:<\/p>\n<ul>\n<li>\u00e0 un niveau, nous avons l&rsquo;abstraction \u00e9tant d\u00e9finie comme l&rsquo;id\u00e9e que nous prenons une id\u00e9e et la repr\u00e9sentons dans une classe,<\/li>\n<li>\u00e0 un autre niveau, nous avons des classes abstraites qui sont utilis\u00e9es pour aider \u00e0 d\u00e9finir les fonctions que les sous-classes doivent impl\u00e9menter.<\/li>\n<\/ul>\n<p>Et si ce n&rsquo;est pas assez d\u00e9routant, nous m\u00e9langeons cela avec des <a href=\"https:\/\/wordpress.mediadoma.com\/fr\/programmation-orientee-objet-comprendre-les-interfaces\/\" title=\"interfaces\">interfaces<\/a> qui fournissent un contrat impl\u00e9mentant des classes qui doivent suivre, puis nous le m\u00e9langeons avec des classes abstraites qui d\u00e9finissent des m\u00e9thodes qui doivent \u00e9galement \u00eatre impl\u00e9ment\u00e9es mais qui peuvent \u00e9galement impl\u00e9menter leurs propres m\u00e9thodes.<\/p>\n<p>Confus encore? Pas de soucis. Le but des trois articles suivants est de faire ce qui suit\u00a0:<\/p>\n<ol>\n<li>D\u00e9finir ce que sont les classes abstraites,<\/li>\n<li>D\u00e9crire les diff\u00e9rentes classes abstraites et interfaces,<\/li>\n<li>Aidez \u00e0 d\u00e9cider quand vous voulez utiliser l&rsquo;un plut\u00f4t que l&rsquo;autre.<\/li>\n<\/ol>\n<p>Cela dit, voici toute l&rsquo;id\u00e9e derri\u00e8re les classes abstraites.<\/p>\n<h2>Comportement d&rsquo;abstraction<\/h2>\n<p>Tout d&rsquo;abord, il y a une diff\u00e9rence entre l&rsquo;abstraction et les classes abstraites. Le premier fait r\u00e9f\u00e9rence \u00e0 l&rsquo;id\u00e9e de repr\u00e9senter quelque chose dans la programmation ; ce dernier fait r\u00e9f\u00e9rence \u00e0 une mani\u00e8re r\u00e9elle d&rsquo;\u00e9crire du code.<\/p>\n<p>Et l&rsquo;une des meilleures fa\u00e7ons que j&rsquo;ai trouv\u00e9es de penser aux classes abstraites dans la programmation orient\u00e9e objet est de les consid\u00e9rer comme ceci\u00a0:<\/p>\n<blockquote>\n<p>Les classes abstraites remplacent l&rsquo;impl\u00e9mentation.<\/p>\n<\/blockquote>\n<p>Peut-\u00eatre une autre fa\u00e7on de les consid\u00e9rer comme des espaces r\u00e9serv\u00e9s. En fin de compte, ils fournissent le comportement que les sous-classes doivent impl\u00e9menter.<\/p>\n<p>En quoi est-ce diff\u00e9rent d&rsquo;une interface\u00a0? Rappelez-vous qu&rsquo;une interface d\u00e9finit une signature pour une fonction (le nom de la fonction, ses arguments et ses modificateurs de visibilit\u00e9) qu&rsquo;une classe doit impl\u00e9menter.<\/p>\n<p>L&rsquo;abstraction, d&rsquo;autre part, fournit un substitut \u00e0 l&rsquo;impl\u00e9mentation qu&rsquo;une sous-classe doit impl\u00e9menter. Mais peut-\u00eatre cela est-il mieux d\u00e9montr\u00e9 par l&rsquo;utilisation de code.<\/p>\n<h3>L&rsquo;abstraction en pratique<\/h3>\n<p>Disons que vous travaillez sur un projet et que vous constatez que vous avez des fonctionnalit\u00e9s qui existent \u00e0 plusieurs endroits. En plus de violer toute l&rsquo;id\u00e9e de DRY, il a \u00e9galement le potentiel d&rsquo;\u00eatre un endroit o\u00f9 vous pouvez extraire une fonctionnalit\u00e9 dans une classe de base et l&rsquo;utiliser \u00e0 nouveau.<\/p>\n<p>Consid\u00e9rons cela dans le contexte d&rsquo;un syst\u00e8me de publication. Ce n&rsquo;est pas n\u00e9cessairement ainsi que WordPress l&rsquo;impl\u00e9mente, mais il utilise une id\u00e9e avec laquelle nous sommes familiers: les taxonomies.<\/p>\n<p>Dans WordPress, rappelons que nous avons des <strong>Tags<\/strong> et <strong>des Cat\u00e9gories<\/strong>. Il existe des diff\u00e9rences subtiles entre les deux (comme si l&rsquo;un \u00e9tait hi\u00e9rarchique ou non), mais ils partagent \u00e9galement des attributs similaires, comme avoir un nom et une limace.<\/p>\n<h3>Une abstraction taxonomique<\/h3>\n<p>Nous pouvons donc commencer par \u00e9crire une classe de taxonomie abstraite qui r\u00e9sume la fonctionnalit\u00e9 commune <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-00-taxonomy-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">dans sa propre classe.<\/a><\/p>\n<pre><code>&lt;?php\n\nabstract class Taxonomy\n{\n\n  private $taxonomyName;\n\n  private $taxonomySlug;\n\n  public function __construct($name) {\n    $this-&gt;taxonomyName = $name;\n    $this-&gt;taxonomySlug = strtolower(str_ireplace(' ', '-', $this-&gt;taxonomyName));\n  }\n\n  public function getName() {\n    return $this-&gt;taxonomyName;\n  }\n\n  public function getSlug() {\n    return $this-&gt;taxonomySlug;\n  }\n\n  abstract protected function isHierarchical();\n  abstract protected function isCategory();\n  abstract protected function isTag();\n\n}<\/code><\/pre>\n<p>Dans le code ci-dessus, vous verrez que j&rsquo;ai fait ce qui suit\u00a0:<\/p>\n<ul>\n<li>a d\u00e9clar\u00e9 la classe <strong>abstraite<\/strong><\/li>\n<li>d\u00e9fini plusieurs attributs qui seront d\u00e9finis dans le constructeur<\/li>\n<li>a assur\u00e9 la mise en \u0153uvre de plusieurs fonctions publiques,<\/li>\n<li>ajout\u00e9 plusieurs m\u00e9thodes prot\u00e9g\u00e9es.<\/li>\n<\/ul>\n<p>La cl\u00e9 \u00e0 retenir de l&rsquo;examen de cette classe est que toute classe qui impl\u00e9mente cette classe abstraite aura automatiquement la fonctionnalit\u00e9 d\u00e9finie dans le constructeur, la fonction <strong>getName<\/strong> et la fonction <strong>getSlug<\/strong>.<\/p>\n<p>Ils n&rsquo;auront cependant pas l&rsquo;impl\u00e9mentation des fonctions <strong>abstraites<\/strong>. C&rsquo;est ce qui reste \u00e0 impl\u00e9menter par les sous-classes (que je partagerai momentan\u00e9ment).<\/p>\n<h3>Une taxonomie concr\u00e8te\u00a0: une \u00e9tiquette<\/h3>\n<p>Maintenant que nous avons d\u00e9fini une classe abstraite, il est possible d&rsquo;impl\u00e9menter l&rsquo;abstraction. <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-01-tag-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Par exemple<\/a> :<\/p>\n<pre><code>&lt;?php\n\nclass Tag extends Taxonomy\n{\n  protected function isHierarchical() {\n    return false;\n  }\n\n  protected function isCategory() {\n    return $this-&gt;isHierarchical;\n  }\n\n  protected function isTag() {\n    return !$this-&gt;isHierarchical;\n  }\n}\n<\/code><\/pre>\n<p>Dans le code ci-dessus, notez que la classe ne fait que fournir l&rsquo;impl\u00e9mentation des fonctions abstraites d\u00e9finies dans la classe abstraite (qui est sp\u00e9cifi\u00e9e par la fonction <strong>extend<\/strong> dans la d\u00e9finition de classe).<\/p>\n<p>Plus loin dans cet article, je partagerai comment tester ce code, mais notez que ce qui pr\u00e9c\u00e8de offre non seulement les fonctionnalit\u00e9s que vous voyez, mais \u00e9galement les fonctionnalit\u00e9s de la classe <strong>Taxonomy<\/strong>.<\/p>\n<h3>Une taxonomie concr\u00e8te: une cat\u00e9gorie<\/h3>\n<p>Avant de jeter un coup d&rsquo;\u0153il \u00e0 cela en action, je souhaite \u00e9galement d\u00e9finir une cat\u00e9gorie. Cela inclura du code qui impl\u00e9mente des fonctions de la classe abstraite mais aussi des fonctions qui lui sont propres.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-02-category-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Voir ci-dessous:<\/a><\/p>\n<pre><code>&lt;?php\nclass Category extends Taxonomy\n{\n  private $parentId = -1;\n\n  protected function isHierarchical() {\n    return true;\n  }\n\n  protected function isCategory() {\n    return $this-&gt;isHierarchical;\n  }\n\n  protected function isTag() {\n    return !$this-&gt;isHierarchical;\n  }\n\n  public function setParentId($parentId) {\n    $this-&gt;parentId = $parentId;\n  }\n\n  public function getParentId() {\n    return $this-&gt;parentId;\n  }\n}\n<\/code><\/pre>\n<p>Ici, nous avons tout ce qui vient avec la classe <strong>Taxonomy<\/strong>, mais nous avons \u00e9galement d\u00e9fini notre propri\u00e9t\u00e9 pour son ID parent et ses m\u00e9thodes getter et setter. Bien que triviale dans ce cas, elle montre comment les cat\u00e9gories, qui sont hi\u00e9rarchiques, peuvent fonctionner.<\/p>\n<p>De plus, si la cat\u00e9gorie n&rsquo;a pas de parent, l&rsquo;ID est d\u00e9fini sur -1, ce qui facilite l&rsquo;\u00e9criture pour les tests automatis\u00e9s ou m\u00eame la v\u00e9rification pour voir si elle a un parent.<\/p>\n<h3>Le voir en action<\/h3>\n<p>Pour faire la d\u00e9monstration de tout ce code, j&rsquo;ai un essentiel qui inclut tout le code dans un seul fichier. En tant que meilleure pratique, je ne le recommande pas. Au lieu de cela, chaque classe doit \u00eatre conserv\u00e9e dans son propre fichier et chaque classe doit appartenir \u00e0 un espace de noms.<\/p>\n<p>Mais comme c&rsquo;est purement \u00e0 des fins de d\u00e9monstration, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-03-demo-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">cela suffit.<\/a><\/p>\n<pre><code>&lt;?php\n\nabstract class Taxonomy\n{\n  private $taxonomyName;\n\n  private $taxonomySlug;\n\n  public function __construct($name) {\n    $this-&gt;taxonomyName = $name;\n    $this-&gt;taxonomySlug = strtolower(str_ireplace(' ', '-', $this-&gt;taxonomyName));\n  }\n\n  public function getName() {\n    return $this-&gt;taxonomyName;\n  }\n\n  public function getSlug() {\n    return $this-&gt;taxonomySlug;\n  }\n\n  abstract protected function isHierarchical();\n  abstract protected function isCategory();\n  abstract protected function isTag();\n\n}\n\n\/*--*\/\n\nclass Tag extends Taxonomy\n{\n  protected function isHierarchical() {\n    return false;\n  }\n\n  protected function isCategory() {\n    return $this-&gt;isHierarchical;\n  }\n\n  protected function isTag() {\n    return !$this-&gt;isHierarchical;\n  }\n}\n\n\/*--*\/\n\nclass Category extends Taxonomy\n{\n  private $parentId = -1;\n\n  protected function isHierarchical() {\n    return true;\n  }\n\n  protected function isCategory() {\n    return $this-&gt;isHierarchical;\n  }\n\n  protected function isTag() {\n    return !$this-&gt;isHierarchical;\n  }\n\n  public function setParentId($parentId) {\n    $this-&gt;parentId = $parentId;\n  }\n\n  public function getParentId() {\n    return $this-&gt;parentId;\n  }\n}\n\n\/*- Tag Demo ----------------------------*\/\n\n$tag = new Tag('Acme Tag');\necho $tag-&gt;getName();\necho $tag-&gt;getSlug();\n\n\/*- Category Demo -----------------------*\/\n\n$category = new Category('Acme Category');\n\necho $category-&gt;getName();\necho $category-&gt;getSlug();\necho $category-&gt;getParentId();\n\n$category-&gt;setParentId(100);\necho $category-&gt;getparentId();\n<\/code><\/pre>\n<p>Lorsque vous ex\u00e9cutez ceci dans la console, vous devriez voir quelque chose comme la sortie suivante\u00a0:<\/p>\n<p>Vous devrez peut-\u00eatre ajouter quelques instructions d&rsquo; <strong>\u00e9cho<\/strong> pour vous assurer qu&rsquo;il cr\u00e9e de nouvelles lignes, mais cela d\u00e9pend de vous.<\/p>\n<h2>Qu&rsquo;en est-il des interfaces\u00a0?<\/h2>\n<p>Donc, \u00e0 ce stade :<\/p>\n<ul>\n<li>nous avons une d\u00e9finition de travail de ce que sont les classes abstraites,<\/li>\n<li>nous avons un exemple de ce \u00e0 quoi ressemblent les classes abstraites,<\/li>\n<li>et nous avons une d\u00e9monstration de travail de la fa\u00e7on dont ils peuvent fonctionner.<\/li>\n<\/ul>\n<p>Ensuite, je vais approfondir la discussion sur les diff\u00e9rences entre les classes abstraites et les interfaces, quand vous voudrez peut-\u00eatre les utiliser les unes sur les autres, ou quand vous voudrez peut-\u00eatre les utiliser conjointement les unes avec les autres.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Source d&rsquo;enregistrement:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>L&rsquo;abstraction du comportement est essentielle dans la programmation orient\u00e9e objet, mais il est important de comprendre comment faire.<\/p>\n","protected":false},"author":1,"featured_media":164837,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[915,893,717,801,841],"tags":[1167],"class_list":["post-230112","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-autre","category-code-2","category-developpeur","category-php-3","category-tutoriels","tag-affiai-fr"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/230112","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/comments?post=230112"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/230112\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media\/164837"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media?parent=230112"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/categories?post=230112"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/tags?post=230112"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}