{"id":230433,"date":"2022-11-22T12:08:00","date_gmt":"2022-11-22T09:08:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230433"},"modified":"2022-11-09T22:22:01","modified_gmt":"2022-11-09T19:22:01","slug":"classi-astratte-parte-1-comportamento-astratto","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/it\/classi-astratte-parte-1-comportamento-astratto\/","title":{"rendered":"Classi astratte, parte 1 &#8211; Comportamento astratto"},"content":{"rendered":"\n<p>Circa un mese fa, <a href=\"https:\/\/tommcfarlin.com\/two-pillars-of-object-oriented-programming-1\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ho scritto di uno<\/a> dei pilastri della programmazione orientata agli oggetti (in particolare l&#8217;astrazione). Nel post, ho definito l&#8217;astrazione come segue:<\/p>\n<blockquote>\n<p>Invece, astrarremo le idee nelle loro classi. E qui c&#8217;\u00e8 un&#8217;idea chiave: una classe dovrebbe rappresentare un sostantivo.<\/p>\n<\/blockquote>\n<p>E sebbene ci\u00f2 sia ancora vero, l&#8217;idea di <strong>classi astratte<\/strong> \u00e8 qualcosa di diverso nella programmazione orientata agli oggetti.<\/p>\n<p>Sembra confuso, giusto? Questo \u00e8:<\/p>\n<ul>\n<li>a un livello, abbiamo l&#8217;astrazione definita come l&#8217;idea che prendiamo un&#8217;idea e la rappresentiamo in una classe,<\/li>\n<li>su un altro livello, abbiamo classi astratte che vengono utilizzate per aiutare a definire le funzioni che le sottoclassi devono implementare.<\/li>\n<\/ul>\n<p>E se ci\u00f2 non \u00e8 abbastanza confuso, lo mescoliamo con <a href=\"https:\/\/tommcfarlin.com\/understanding-interfaces\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">interfacce<\/a> che forniscono un contratto che le classi di implementazione devono seguire, e quindi lo mescoliamo con classi astratte che definiscono metodi che devono anche essere implementati ma possono anche implementare metodi propri.<\/p>\n<p>Confuso ancora? Nessun problema. Il punto centrale dei prossimi tre post \u00e8 di fare quanto segue:<\/p>\n<ol>\n<li>Definisci cosa sono le classi astratte,<\/li>\n<li>Descrivi le diverse classi e interfacce astratte,<\/li>\n<li>Aiuta a decidere quando vuoi usare uno sull&#8217;altro.<\/li>\n<\/ol>\n<p>Detto questo, ecco l&#8217;intera idea dietro le classi astratte.<\/p>\n<h2>Comportamento astratto<\/h2>\n<p>Innanzitutto, c&#8217;\u00e8 una differenza nell&#8217;astrazione e nelle classi astratte. Il primo si riferisce all&#8217;idea di rappresentare qualcosa nella programmazione; quest&#8217;ultimo si riferisce a un modo effettivo di scrivere codice.<\/p>\n<p>E uno dei modi migliori che ho trovato per pensare alle classi astratte nella programmazione orientata agli oggetti \u00e8 pensarle in questo modo:<\/p>\n<blockquote>\n<p>Le classi astratte sostituiscono l&#8217;implementazione.<\/p>\n<\/blockquote>\n<p>Forse un altro modo di pensarli sono i segnaposto. Infine, forniscono il comportamento che le sottoclassi devono implementare.<\/p>\n<p>In che modo \u00e8 diverso da un&#8217;interfaccia? Ricorda che un&#8217;interfaccia definisce una firma per una funzione (il nome della funzione, i suoi argomenti e i suoi modificatori di visibilit\u00e0) che una classe deve implementare.<\/p>\n<p>L&#8217;astrazione, d&#8217;altra parte, fornisce un sostituto per l&#8217;implementazione che una sottoclasse deve implementare. Ma forse questo \u00e8 meglio dimostrato attraverso l&#8217;uso del codice.<\/p>\n<h3>L&#8217;astrazione in pratica<\/h3>\n<p>Diciamo che stai lavorando a un progetto e scopri di avere funzionalit\u00e0 che esistono in pi\u00f9 di un posto. Oltre a violare l&#8217;intera idea di DRY, ha anche il potenziale per essere un luogo in cui \u00e8 possibile astrarre funzionalit\u00e0 in una classe base e riutilizzarla.<\/p>\n<p>Consideriamo questo nel contesto di un sistema editoriale. Questo non \u00e8 necessariamente il modo in cui WordPress lo implementa, ma utilizza un&#8217;idea che ci \u00e8 familiare: le tassonomie.<\/p>\n<p>In WordPress, ricorda che abbiamo <strong>Tag<\/strong> e <strong>Categorie<\/strong>. Ci sono sottili differenze tra i due (come se uno fosse gerarchico o meno), ma condividono anche attributi simili come avere un nome e una lumaca.<\/p>\n<h3>Un&#8217;astrazione tassonomica<\/h3>\n<p>Quindi possiamo iniziare scrivendo una classe Tassonomia astratta che astrae la funzionalit\u00e0 comune <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-00-taxonomy-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">nella propria 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>Nel codice sopra, vedrai che ho fatto quanto segue:<\/p>\n<ul>\n<li>ha dichiarato l&#8217; <strong>abstract della classe<\/strong><\/li>\n<li>definito diversi attributi che verranno impostati nel costruttore<\/li>\n<li>fornito diverse funzioni pubbliche con l&#8217;attuazione,<\/li>\n<li>aggiunto diversi metodi protetti.<\/li>\n<\/ul>\n<p>Il punto chiave dall&#8217;esame di questa classe \u00e8 che qualsiasi classe che implementa questa classe astratta avr\u00e0 automaticamente la funzionalit\u00e0 definita nel costruttore, la funzione <strong>getName<\/strong> e la funzione <strong>getSlug<\/strong>.<\/p>\n<p>Non avranno, tuttavia, l&#8217;implementazione delle funzioni <strong>astratte<\/strong>. Questi sono ci\u00f2 che resta da implementare dalle sottoclassi (che condivider\u00f2 momentaneamente).<\/p>\n<h3>Una tassonomia concreta: un tag<\/h3>\n<p>Ora che abbiamo una classe astratta definita, \u00e8 possibile implementare effettivamente l&#8217;astrazione. <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-01-tag-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Ad esempio<\/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>Nel codice sopra, si noti che tutto ci\u00f2 che la classe fa \u00e8 fornire l&#8217;implementazione per le funzioni astratte definite nella classe astratta (che \u00e8 specificata dalla funzione <strong>extends<\/strong> nella definizione della classe).<\/p>\n<p>Pi\u00f9 avanti in questo articolo, condivider\u00f2 come testare questo codice, ma noter\u00f2 che quanto sopra offre non solo la funzionalit\u00e0 che vedi, ma anche la funzionalit\u00e0 della classe <strong>Tassonomia<\/strong>.<\/p>\n<h3>Una tassonomia concreta: una categoria<\/h3>\n<p>Prima di dare un&#8217;occhiata a questo in azione, voglio definire anche una categoria. Ci\u00f2 includer\u00e0 codice che implementa funzioni dalla classe astratta ma anche funzioni proprie.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-02-category-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Vedi sotto:<\/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>Qui abbiamo tutto ci\u00f2 che viene fornito con la classe <strong>Tassonomia<\/strong>, ma abbiamo anche definito la nostra propriet\u00e0 per il suo ID genitore e metodi getter e setter. Anche se banale in questo caso, mostra come le categorie, che sono gerarchiche, possono funzionare.<\/p>\n<p>Inoltre, se la categoria non ha un genitore, l&#8217;ID \u00e8 impostato su -1, il che semplifica la scrittura per i test automatici o persino il controllo per vedere se ha un genitore.<\/p>\n<h3>Vedendolo in azione<\/h3>\n<p>Per dimostrare l&#8217;intero codice, ho un&#8217;idea che include tutto il codice in un unico file. Come best practice, non lo consiglio. Invece, ogni classe dovrebbe essere conservata nel proprio file e ogni classe dovrebbe appartenere a uno spazio dei nomi.<\/p>\n<p>Ma poich\u00e9 questo \u00e8 puramente a scopo dimostrativo, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-03-demo-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">\u00e8 sufficiente.<\/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>Quando lo esegui nella console, dovresti vedere qualcosa come il seguente output:<\/p>\n<p>Potrebbe essere necessario aggiungere alcune dichiarazioni di <strong>eco<\/strong> per assicurarti che stia creando nuove linee, ma dipende da te.<\/p>\n<h2>E le interfacce?<\/h2>\n<p>Quindi, a questo punto:<\/p>\n<ul>\n<li>abbiamo una definizione funzionante di cosa sono le classi astratte,<\/li>\n<li>abbiamo un esempio di come appaiono le classi astratte,<\/li>\n<li>e abbiamo una demo funzionante di come possono esibirsi.<\/li>\n<\/ul>\n<p>Successivamente, far\u00f2 un tuffo pi\u00f9 approfondito nella discussione delle differenze tra classi e interfacce astratte, quando potresti voler usare l&#8217;una sull&#8217;altra o quando potresti volerle usare insieme l&#8217;una all&#8217;altra.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte di registrazione:  <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&#8217;astrazione del comportamento \u00e8 fondamentale nella programmazione orientata agli oggetti, ma capire come fare \u00e8 importante.<\/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":[918,896,804,720,844],"tags":[1168],"class_list":["post-230433","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-altro","category-codice","category-php-6","category-sviluppatore","category-tutorial","tag-affiai-it"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts\/230433","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/comments?post=230433"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts\/230433\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/media\/164837"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/media?parent=230433"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/categories?post=230433"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/tags?post=230433"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}