{"id":230206,"date":"2022-11-22T11:26:00","date_gmt":"2022-11-22T08:26:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230206"},"modified":"2022-11-22T11:32:14","modified_gmt":"2022-11-22T08:32:14","slug":"aulas-de-resumo-parte-1-comportamento-de-abstracao","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/aulas-de-resumo-parte-1-comportamento-de-abstracao\/","title":{"rendered":"Aulas de Resumo, Parte 1 &#8211; Comportamento de Abstra\u00e7\u00e3o"},"content":{"rendered":"\n<p>Cerca de um m\u00eas atr\u00e1s, <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/os-dois-primeiros-pilares-da-poo\/\" title=\"escrevi sobre um\">escrevi sobre um<\/a> dos pilares da programa\u00e7\u00e3o orientada a objetos (especificamente a abstra\u00e7\u00e3o). No post, defini abstra\u00e7\u00e3o como o seguinte:<\/p>\n<blockquote>\n<p>Em vez disso, vamos abstrair ideias em suas classes. E h\u00e1 uma ideia chave aqui: uma classe deve representar um substantivo.<\/p>\n<\/blockquote>\n<p>E embora isso ainda seja verdade, a ideia de <strong>classes abstratas<\/strong> \u00e9 algo diferente na programa\u00e7\u00e3o orientada a objetos.<\/p>\n<p>Parece confuso, certo? Aquilo \u00e9:<\/p>\n<ul>\n<li>em um n\u00edvel, temos abstra\u00e7\u00e3o sendo definida como a ideia de que pegamos uma ideia e a representamos em uma classe,<\/li>\n<li>em outro n\u00edvel, temos classes abstratas que s\u00e3o usadas para ajudar a definir fun\u00e7\u00f5es que as subclasses devem implementar.<\/li>\n<\/ul>\n<p>E se isso n\u00e3o for confuso o suficiente, misturamos isso com <a href=\"https:\/\/wordpress.mediadoma.com\/pt-pt\/programacao-orientada-a-objetos-entendendo-interfaces\/\" title=\"interfaces\">interfaces<\/a> que fornecem um contrato de implementa\u00e7\u00e3o de classes que deve seguir, e ent\u00e3o misturamos com classes abstratas que definem m\u00e9todos que tamb\u00e9m devem ser implementados, mas tamb\u00e9m podem implementar m\u00e9todos pr\u00f3prios.<\/p>\n<p>Confuso ainda? Sem problemas. O objetivo dos pr\u00f3ximos tr\u00eas posts \u00e9 fazer o seguinte:<\/p>\n<ol>\n<li>Defina o que s\u00e3o classes abstratas,<\/li>\n<li>Descrever o diferente em classes abstratas e interfaces,<\/li>\n<li>Ajude a decidir quando voc\u00ea quer usar um sobre o outro.<\/li>\n<\/ol>\n<p>Com isso dito, aqui est\u00e1 toda a ideia por tr\u00e1s das classes abstratas.<\/p>\n<h2>Comportamento de abstra\u00e7\u00e3o<\/h2>\n<p>Em primeiro lugar, h\u00e1 uma diferen\u00e7a na abstra\u00e7\u00e3o e nas classes abstratas. A primeira refere-se \u00e0 ideia de representar algo na programa\u00e7\u00e3o; o \u00faltimo refere-se a uma maneira real de escrever c\u00f3digo.<\/p>\n<p>E uma das melhores maneiras que encontrei para pensar sobre classes abstratas na programa\u00e7\u00e3o orientada a objetos \u00e9 pensar nelas assim:<\/p>\n<blockquote>\n<p>As classes abstratas s\u00e3o um substituto para a implementa\u00e7\u00e3o.<\/p>\n<\/blockquote>\n<p>Talvez outra maneira de pensar neles seja como espa\u00e7os reservados. Em \u00faltima an\u00e1lise, eles fornecem o comportamento que as subclasses devem implementar.<\/p>\n<p>Como isso \u00e9 diferente de uma interface? Lembre-se de que uma interface define uma assinatura para uma fun\u00e7\u00e3o (o nome da fun\u00e7\u00e3o, seus argumentos e seus modificadores de visibilidade) que uma classe deve implementar.<\/p>\n<p>A abstra\u00e7\u00e3o, por outro lado, fornece um substituto para a implementa\u00e7\u00e3o que uma subclasse deve implementar. Mas talvez isso seja melhor demonstrado atrav\u00e9s do uso de c\u00f3digo.<\/p>\n<h3>Abstra\u00e7\u00e3o na pr\u00e1tica<\/h3>\n<p>Digamos que voc\u00ea esteja trabalhando em um projeto e descubra que tem uma funcionalidade que existe em mais de um lugar. Al\u00e9m de violar toda a ideia de DRY, ele tamb\u00e9m tem potencial para ser um lugar onde voc\u00ea pode abstrair a funcionalidade em uma classe base e us\u00e1-la novamente.<\/p>\n<p>Vamos considerar isso no contexto de um sistema de publica\u00e7\u00e3o. N\u00e3o \u00e9 necessariamente assim que o WordPress o implementa, mas usa uma ideia com a qual estamos familiarizados: Taxonomias.<\/p>\n<p>No WordPress, lembre-se que temos <strong>Tags<\/strong> e <strong>Categorias<\/strong>. Existem diferen\u00e7as sutis entre os dois (como se um \u00e9 hier\u00e1rquico ou n\u00e3o), mas eles tamb\u00e9m compartilham atributos semelhantes, como ter um nome e um slug.<\/p>\n<h3>Uma Abstra\u00e7\u00e3o de Taxonomia<\/h3>\n<p>Assim, podemos come\u00e7ar escrevendo uma classe abstrata de Taxonomia que abstrai a funcionalidade comum <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-00-taxonomy-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">em sua pr\u00f3pria 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>No c\u00f3digo acima, voc\u00ea ver\u00e1 que fiz o seguinte:<\/p>\n<ul>\n<li>declarou o <strong>resumo da classe<\/strong><\/li>\n<li>definiu v\u00e1rios atributos que ser\u00e3o definidos no construtor<\/li>\n<li>desde v\u00e1rias fun\u00e7\u00f5es p\u00fablicas com implementa\u00e7\u00e3o,<\/li>\n<li>adicionou v\u00e1rios m\u00e9todos protegidos.<\/li>\n<\/ul>\n<p>A principal vantagem de olhar para essa classe \u00e9 que qualquer classe que implemente essa classe abstrata ter\u00e1 automaticamente a funcionalidade definida no construtor, na fun\u00e7\u00e3o <strong>getName<\/strong> e na fun\u00e7\u00e3o <strong>getSlug<\/strong>.<\/p>\n<p>Eles n\u00e3o ter\u00e3o, no entanto, a implementa\u00e7\u00e3o das fun\u00e7\u00f5es <strong>abstratas<\/strong>. Isso \u00e9 o que resta para ser implementado pelas subclasses (que compartilharei momentaneamente).<\/p>\n<h3>Uma taxonomia concreta: uma etiqueta<\/h3>\n<p>Agora que temos uma classe abstrata definida, \u00e9 poss\u00edvel realmente implementar a abstra\u00e7\u00e3o. <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-01-tag-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Por exemplo<\/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>No c\u00f3digo acima, observe que tudo que a classe faz \u00e9 fornecer a implementa\u00e7\u00e3o para as fun\u00e7\u00f5es abstratas definidas na classe abstrata (que \u00e9 especificada pela fun\u00e7\u00e3o <strong>extends<\/strong> na defini\u00e7\u00e3o da classe).<\/p>\n<p>Mais adiante neste artigo, compartilharei como testar esse c\u00f3digo, mas observe que o acima n\u00e3o apenas oferece a funcionalidade que voc\u00ea v\u00ea, mas tamb\u00e9m a funcionalidade da classe <strong>Taxonomy<\/strong>.<\/p>\n<h3>Uma taxonomia concreta: uma categoria<\/h3>\n<p>Antes de dar uma olhada nisso em a\u00e7\u00e3o, quero definir uma categoria tamb\u00e9m. Isso incluir\u00e1 c\u00f3digo que implementa fun\u00e7\u00f5es da classe abstrata, mas tamb\u00e9m fun\u00e7\u00f5es pr\u00f3prias.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-02-category-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Veja abaixo:<\/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>Aqui, temos tudo que vem com a classe <strong>Taxonomy<\/strong>, mas tamb\u00e9m definimos nossa propriedade para seu ID pai e m\u00e9todos getter e setter. Embora trivial neste caso, mostra como as categorias, que s\u00e3o hier\u00e1rquicas, podem funcionar.<\/p>\n<p>Al\u00e9m disso, se a categoria n\u00e3o tiver pai, o ID ser\u00e1 definido como -1, o que facilita a grava\u00e7\u00e3o para testes automatizados ou at\u00e9 mesmo verificar se tem um pai.<\/p>\n<h3>Vendo isso em a\u00e7\u00e3o<\/h3>\n<p>Para demonstrar todo esse c\u00f3digo, tenho uma ess\u00eancia que inclui todo o c\u00f3digo em um \u00fanico arquivo. Como pr\u00e1tica recomendada, n\u00e3o recomendo isso. Em vez disso, cada classe deve ser mantida em seu pr\u00f3prio arquivo e cada classe deve pertencer a um namespace.<\/p>\n<p>Mas como isso \u00e9 puramente para fins de demonstra\u00e7\u00e3o, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-03-demo-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">\u00e9 suficiente.<\/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>Ao executar isso no console, voc\u00ea dever\u00e1 ver algo como a seguinte sa\u00edda:<\/p>\n<p>Voc\u00ea pode precisar adicionar algumas declara\u00e7\u00f5es de <strong>eco<\/strong> para ter certeza de que est\u00e1 criando novas linhas, mas isso \u00e9 com voc\u00ea.<\/p>\n<h2>E as interfaces?<\/h2>\n<p>Ent\u00e3o, neste momento:<\/p>\n<ul>\n<li>temos uma defini\u00e7\u00e3o funcional do que s\u00e3o classes abstratas,<\/li>\n<li>temos um exemplo de como s\u00e3o as classes abstratas,<\/li>\n<li>e temos uma demonstra\u00e7\u00e3o funcional de como eles podem funcionar.<\/li>\n<\/ul>\n<p>Em seguida, vou me aprofundar na discuss\u00e3o das diferen\u00e7as entre classes abstratas e interfaces, quando voc\u00ea pode querer usar uma sobre a outra, ou quando voc\u00ea pode querer us\u00e1-las em conjunto.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Abstrair o comportamento \u00e9 fundamental na programa\u00e7\u00e3o orientada a objetos, mas entender como fazer \u00e9 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":[898,722,920,806,846],"tags":[1170],"class_list":["post-230206","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-outro","category-php-8","category-tutoriais","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/230206","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=230206"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/230206\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/164837"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=230206"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=230206"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=230206"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}