{"id":229682,"date":"2022-11-22T12:02:00","date_gmt":"2022-11-22T09:02:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=229682"},"modified":"2022-11-22T12:27:17","modified_gmt":"2022-11-22T09:27:17","slug":"abstrakta-klasser-del-1-abstraherande-beteende","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/sv\/abstrakta-klasser-del-1-abstraherande-beteende\/","title":{"rendered":"Abstrakta klasser, del 1 &#8211; Abstraherande beteende"},"content":{"rendered":"\n<p>F\u00f6r ungef\u00e4r en m\u00e5nad sedan skrev <a href=\"https:\/\/wordpress.mediadoma.com\/sv\/de-tvaa-foersta-pelarna-i-oop\/\" title=\"jag om en\">jag om en<\/a> av pelarna i objektorienterad programmering (s\u00e4rskilt abstraktion). I inl\u00e4gget definierade jag abstraktion som f\u00f6ljande:<\/p>\n<blockquote>\n<p>Ist\u00e4llet kommer vi att abstrahera id\u00e9er i deras klasser. Och det finns en nyckelid\u00e9 h\u00e4r: En klass ska representera ett substantiv.<\/p>\n<\/blockquote>\n<p>Och \u00e4ven om det fortfarande \u00e4r sant, \u00e4r id\u00e9n med <strong>abstrakta klasser<\/strong> n\u00e5got som \u00e4r annorlunda i objektorienterad programmering.<\/p>\n<p>Det l\u00e5ter f\u00f6rvirrande, eller hur? Det \u00e4r:<\/p>\n<ul>\n<li>p\u00e5 en niv\u00e5 har vi abstraktion definierad som id\u00e9n att vi tar en id\u00e9 och representerar den i en klass,<\/li>\n<li>p\u00e5 en annan niv\u00e5 har vi abstrakta klasser som anv\u00e4nds f\u00f6r att hj\u00e4lpa till att definiera funktioner som underklasser m\u00e5ste implementera.<\/li>\n<\/ul>\n<p>Och om det inte \u00e4r tillr\u00e4ckligt f\u00f6rvirrande, blandar vi detta med <a href=\"https:\/\/wordpress.mediadoma.com\/sv\/objektorienterad-programmering-foerstaa-graenssnitt\/\" title=\"gr\u00e4nssnitt\">gr\u00e4nssnitt<\/a> som ger ett kontrakt som implementerande klasser m\u00e5ste f\u00f6lja, och sedan blandar vi det med abstrakta klasser som definierar metoder som ocks\u00e5 m\u00e5ste implementeras men som ocks\u00e5 kan implementera egna metoder.<\/p>\n<p>F\u00f6rvirrad \u00e4nnu? Inga problem. Hela po\u00e4ngen med de kommande tre inl\u00e4ggen \u00e4r att g\u00f6ra f\u00f6ljande:<\/p>\n<ol>\n<li>Definiera vad abstrakta klasser \u00e4r,<\/li>\n<li>Beskriv de olika i abstrakta klasser och gr\u00e4nssnitt,<\/li>\n<li>Hj\u00e4lp att best\u00e4mma n\u00e4r du vill anv\u00e4nda den ena framf\u00f6r den andra.<\/li>\n<\/ol>\n<p>Med det sagt, h\u00e4r \u00e4r hela id\u00e9n bakom abstrakta klasser.<\/p>\n<h2>Abstraherande beteende<\/h2>\n<p>F\u00f6rst och fr\u00e4mst finns det en skillnad i abstraktionsklasser och abstrakta klasser. Den f\u00f6rra h\u00e4nvisar till id\u00e9n att representera n\u00e5got i programmering; det senare h\u00e4nvisar till ett faktiskt s\u00e4tt att skriva kod.<\/p>\n<p>Och ett av de b\u00e4sta s\u00e4tten jag har hittat p\u00e5 vad jag tycker om abstrakta klasser i objektorienterad programmering \u00e4r att t\u00e4nka p\u00e5 dem s\u00e5 h\u00e4r:<\/p>\n<blockquote>\n<p>Abstrakta klasser \u00e4r ett substitut f\u00f6r implementering.<\/p>\n<\/blockquote>\n<p>Ett annat s\u00e4tt att t\u00e4nka p\u00e5 dem \u00e4r kanske som platsh\u00e5llare. I slut\u00e4ndan ger de det beteende som underklasserna m\u00e5ste implementera.<\/p>\n<p>Hur skiljer sig detta fr\u00e5n ett gr\u00e4nssnitt? Kom ih\u00e5g att ett gr\u00e4nssnitt definierar en signatur f\u00f6r en funktion (funktionsnamnet, dess argument och dess synlighetsmodifierare) som en klass m\u00e5ste implementera.<\/p>\n<p>Abstraktion, \u00e5 andra sidan, ger ett substitut f\u00f6r implementering som en underklass m\u00e5ste implementera. Men kanske visas detta b\u00e4st genom att anv\u00e4nda kod.<\/p>\n<h3>Abstraktion i praktiken<\/h3>\n<p>L\u00e5t oss s\u00e4ga att du arbetar med ett projekt och du uppt\u00e4cker att du har funktionalitet som finns p\u00e5 mer \u00e4n ett st\u00e4lle. F\u00f6rutom att bryta mot hela id\u00e9n med DRY, har det ocks\u00e5 potential att vara en plats d\u00e4r du kan abstrahera funktionalitet till en basklass och anv\u00e4nda den igen.<\/p>\n<p>L\u00e5t oss \u00f6verv\u00e4ga detta i samband med ett publiceringssystem. Det \u00e4r inte n\u00f6dv\u00e4ndigtvis hur WordPress implementerar det, men det anv\u00e4nder en id\u00e9 som vi \u00e4r bekanta med: taxonomier.<\/p>\n<p>Kom ih\u00e5g att vi har <strong>taggar<\/strong> och <strong>kategorier<\/strong> i WordPress. Det finns subtila skillnader mellan de tv\u00e5 (som om en \u00e4r hierarkisk eller inte), men de delar ocks\u00e5 liknande attribut som att ha ett namn och en snigel.<\/p>\n<h3>En taxonomiabstraktion<\/h3>\n<p>S\u00e5 vi kan b\u00f6rja med att skriva en abstrakt Taxonomy-klass som abstraherar den gemensamma funktionaliteten <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-00-taxonomy-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">till sin egen klass.<\/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>I koden ovan ser du att jag har gjort f\u00f6ljande:<\/p>\n<ul>\n<li>f\u00f6rklarade klassen <strong>abstrakt<\/strong><\/li>\n<li>definierat flera attribut som kommer att st\u00e4llas in i konstruktorn<\/li>\n<li>tillhandah\u00e5llit flera offentliga funktioner med implementering,<\/li>\n<li>lagt till flera skyddade metoder.<\/li>\n<\/ul>\n<p>Det viktigaste med att titta p\u00e5 den h\u00e4r klassen \u00e4r att varje klass som implementerar den h\u00e4r abstrakta klassen automatiskt kommer att ha den funktionalitet som definieras i konstruktorn, funktionen <strong>getName och funktionen<\/strong> <strong>getSlug<\/strong>.<\/p>\n<p>De kommer dock inte att ha implementeringen av de <strong>abstrakta<\/strong> funktionerna. Det \u00e4r det som \u00e5terst\u00e5r att implementera av underklasserna (som jag kommer att dela med mig av ett \u00f6gonblick).<\/p>\n<h3>En konkret taxonomi: en tagg<\/h3>\n<p>Nu n\u00e4r vi har en abstrakt klass definierad \u00e4r det m\u00f6jligt att faktiskt implementera abstraktionen. <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-01-tag-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Till exempel<\/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>I koden ovan, l\u00e4gg m\u00e4rke till att allt klassen g\u00f6r \u00e4r att tillhandah\u00e5lla implementeringen av de abstrakta funktionerna som definieras i abstraktklassen (vilket specificeras av funktionen <strong>extends<\/strong> i klassdefinitionen).<\/p>\n<p>Senare i den h\u00e4r artikeln kommer jag att dela hur man testar den h\u00e4r koden men notera att ovanst\u00e5ende inte bara erbjuder den funktionalitet som du ser utan ocks\u00e5 funktionaliteten f\u00f6r klassen <strong>Taxonomy<\/strong>.<\/p>\n<h3>En konkret taxonomi: en kategori<\/h3>\n<p>Innan jag tar en titt p\u00e5 detta i praktiken vill jag definiera en kategori ocks\u00e5. Detta kommer att inkludera kod som implementerar funktioner fr\u00e5n den abstrakta klassen men ocks\u00e5 egna funktioner.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-02-category-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Se nedan:<\/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>H\u00e4r har vi allt som f\u00f6ljer med klassen <strong>Taxonomy<\/strong>, men vi har ocks\u00e5 definierat v\u00e5r egenskap f\u00f6r dess f\u00f6r\u00e4ldra-ID och getter- och settermetoder. \u00c4ven om det \u00e4r trivialt i det h\u00e4r fallet, visar det hur kategorier, som \u00e4r hierarkiska, kan fungera.<\/p>\n<p>Vidare, om kategorin inte har n\u00e5gon f\u00f6r\u00e4lder, st\u00e4lls ID:t till -1 vilket g\u00f6r det enkelt att skriva f\u00f6r automatisk testning eller till och med kontrollera om den har en f\u00f6r\u00e4lder.<\/p>\n<h3>Att se det i aktion<\/h3>\n<p>F\u00f6r att demo hela den h\u00e4r koden har jag en sammanfattning som inkluderar all kod i en enda fil. Som en b\u00e4sta praxis rekommenderar jag inte detta. Ist\u00e4llet b\u00f6r varje klass h\u00e5llas i sin egen fil, och varje klass b\u00f6r tillh\u00f6ra ett namnomr\u00e5de.<\/p>\n<p>Men eftersom detta \u00e4r enbart i demonstrationssyfte <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-03-demo-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">r\u00e4cker det.<\/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>N\u00e4r du k\u00f6r detta i konsolen b\u00f6r du se n\u00e5got i stil med f\u00f6ljande utdata:<\/p>\n<p>Du kan beh\u00f6va l\u00e4gga till n\u00e5gra <strong>ekosatser<\/strong> f\u00f6r att se till att det skapar nya linjer, men det \u00e4r upp till dig.<\/p>\n<h2>Hur \u00e4r det med gr\u00e4nssnitt?<\/h2>\n<p>S\u00e5, vid det h\u00e4r laget:<\/p>\n<ul>\n<li>vi har en fungerande definition av vad abstrakta klasser \u00e4r,<\/li>\n<li>vi har ett exempel p\u00e5 hur abstrakta klasser ser ut,<\/li>\n<li>och vi har en fungerande demo av hur de kan prestera.<\/li>\n<\/ul>\n<p>D\u00e4refter ska jag ta en djupare dykning i att diskutera skillnaderna mellan abstrakta klasser och gr\u00e4nssnitt, n\u00e4r du kanske vill anv\u00e4nda den ena framf\u00f6r den andra, eller n\u00e4r du kanske vill anv\u00e4nda dem i kombination med varandra.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Inspelningsk\u00e4lla:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Abstraherande beteende \u00e4r avg\u00f6rande i objektorienterad programmering, men att f\u00f6rst\u00e5 hur man g\u00f6r \u00e4r viktigt.<\/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":[848,901,922,807,724],"tags":[1173],"class_list":["post-229682","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-handledningar","category-koda","category-oevrig","category-php-9","category-utvecklaren","tag-affiai-sv"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts\/229682","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/comments?post=229682"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts\/229682\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/media\/164837"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/media?parent=229682"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/categories?post=229682"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/tags?post=229682"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}