{"id":229690,"date":"2022-11-22T11:53:00","date_gmt":"2022-11-22T08:53:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=229690"},"modified":"2022-11-22T11:54:21","modified_gmt":"2022-11-22T08:54:21","slug":"abstraktsed-klassid-1-osa-abstraktne-kaeitumine","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/et\/abstraktsed-klassid-1-osa-abstraktne-kaeitumine\/","title":{"rendered":"Abstraktsed klassid, 1. osa \u2013 Abstraktne k\u00e4itumine"},"content":{"rendered":"\n<p>Umbes kuu aega tagasi <a href=\"https:\/\/wordpress.mediadoma.com\/et\/oop-kaks-esimest-sammast\/\" title=\"kirjutasin\">kirjutasin<\/a> objektorienteeritud programmeerimise \u00fchest tugisambast (t\u00e4psemalt Abstraction). Postituses m\u00e4\u00e4ratlesin abstraktsiooni j\u00e4rgmiselt:<\/p>\n<blockquote>\n<p>Selle asemel abstraheerime ideid nende klassidesse. Ja siin on p\u00f5hiidee: klass peaks esindama nimis\u00f5na.<\/p>\n<\/blockquote>\n<p><strong>Ja kuigi see on endiselt t\u00f5si, on abstraktsete klasside<\/strong> idee objektorienteeritud programmeerimises midagi muud.<\/p>\n<p>K\u00f5lab segaselt, eks? See on:<\/p>\n<ul>\n<li>\u00fchel tasandil on abstraktsioon defineeritud kui idee, et v\u00f5tame idee ja esindame seda klassis,<\/li>\n<li>teisel tasandil on meil abstraktsed klassid, mida kasutatakse funktsioonide m\u00e4\u00e4ratlemiseks, mida alamklassid peavad rakendama.<\/li>\n<\/ul>\n<p>Ja kui see ei ole piisavalt segane, segame selle <a href=\"https:\/\/wordpress.mediadoma.com\/et\/objektorienteeritud-programmeerimine-liideste-moistmine\/\" title=\"liidestega\">liidestega<\/a>, mis n\u00e4evad ette lepingu, millele peavad j\u00e4rgnema rakendamisklassid, ja seej\u00e4rel abstraktsete klassidega, mis m\u00e4\u00e4ratlevad meetodid, mida tuleb samuti rakendada, kuid mis v\u00f5ivad rakendada ka oma meetodeid.<\/p>\n<p>Kas olete veel segaduses? \u00c4ra muretse. J\u00e4rgmise kolme postituse m\u00f5te on teha j\u00e4rgmist:<\/p>\n<ol>\n<li>M\u00e4\u00e4ratlege, mis on abstraktsed klassid,<\/li>\n<li>Kirjeldage abstraktsete klasside ja liideste erinevusi,<\/li>\n<li>Aidake otsustada, millal soovite \u00fcht teist kasutada.<\/li>\n<\/ol>\n<p>Seda \u00f6eldes on siin kogu abstraktsete klasside idee.<\/p>\n<h2>Abstraheeriv k\u00e4itumine<\/h2>\n<p>Esiteks on erinevus abstraktsioonide ja abstraktsete klasside vahel. Esimene viitab ideele kujutada programmeerimises midagi; viimane viitab tegelikule koodi kirjutamise viisile.<\/p>\n<p>Ja \u00fcks parimaid viise, kuidas objektorienteeritud programmeerimise abstraktsetest klassidest m\u00f5elda, on m\u00f5elda neile j\u00e4rgmiselt:<\/p>\n<blockquote>\n<p>Abstraktsed klassid asendavad rakendamist.<\/p>\n<\/blockquote>\n<p>V\u00f5ib-olla on veel \u00fcks viis neist m\u00f5elda kohahoidjatena. L\u00f5ppkokkuv\u00f5ttes pakuvad need k\u00e4itumist, mida alamklassid peavad rakendama.<\/p>\n<p>Kuidas see erineb liidesest? Pidage meeles, et liides m\u00e4\u00e4rab funktsioonile allkirja (funktsiooni nimi, argumendid ja n\u00e4htavuse modifikaatorid), mida klass peab rakendama.<\/p>\n<p>Abstraktsioon seevastu asendab teostust, mida alamklass peab rakendama. Kuid v\u00f5ib-olla n\u00e4itab see k\u00f5ige paremini koodi kasutamist.<\/p>\n<h3>Abstraktsioon praktikas<\/h3>\n<p>Oletame, et t\u00f6\u00f6tate projekti kallal ja leiate, et teil on funktsioone, mis on olemas rohkem kui \u00fches kohas. Lisaks kogu DRY idee rikkumisele v\u00f5ib see olla ka koht, kus saate funktsionaalsust p\u00f5hiklassiks abstraktseks v\u00f5tta ja seda uuesti kasutada.<\/p>\n<p>Vaatleme seda kirjastamiss\u00fcsteemi kontekstis. WordPress ei pruugi seda rakendada, kuid see kasutab meile tuttavat ideed: taksonoomiad.<\/p>\n<p>Pidage meeles, et WordPressis on <strong>sildid<\/strong> ja <strong>kategooriad<\/strong>. Nende kahe vahel on v\u00e4ikesed erinevused (nt kas see on hierarhiline v\u00f5i mitte), kuid neil on ka sarnased atribuudid, nagu nimi ja n\u00e4lkjas.<\/p>\n<h3>Taksonoomia abstraktsioon<\/h3>\n<p>Seega v\u00f5ime alustada abstraktse taksonoomia klassi kirjutamisest, mis koondab \u00fchise funktsionaalsuse <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-00-taxonomy-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">oma klassi.<\/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>\u00dclaltoodud koodis n\u00e4ete, et olen teinud j\u00e4rgmist.<\/p>\n<ul>\n<li>kuulutas klassi <strong>abstraktseks<\/strong><\/li>\n<li>m\u00e4\u00e4ratles mitu atribuuti, mis konstruktoris seadistatakse<\/li>\n<li>t\u00e4itnud mitmeid avalikke funktsioone,<\/li>\n<li>lisatud mitu kaitstud meetodit.<\/li>\n<\/ul>\n<p>Selle klassi vaatamise peamine eelis on see, et igal klassil, mis seda abstraktset klassi rakendab, on automaatselt konstruktoris m\u00e4\u00e4ratletud funktsionaalsus, funktsioon <strong>getName ja funktsioon<\/strong> <strong>getSlug<\/strong>.<\/p>\n<p>Neil ei ole aga <strong>abstraktsete<\/strong> funktsioonide rakendamist. See on see, mis j\u00e4\u00e4b alamklasside rakendada (mida ma kohe jagan).<\/p>\n<h3>Konkreetne taksonoomia: silt<\/h3>\n<p>N\u00fc\u00fcd, kui meil on abstraktne klass m\u00e4\u00e4ratletud, on v\u00f5imalik abstraktsiooni ka tegelikult rakendada. <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-01-tag-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">N\u00e4iteks<\/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>\u00dclaltoodud koodis pange t\u00e4hele, et k\u00f5ik, mida klass teeb, pakub abstraktsetes klassides m\u00e4\u00e4ratletud abstraktsete funktsioonide realiseerimist (mis on m\u00e4\u00e4ratud <strong>klassi<\/strong> m\u00e4\u00e4ratluses oleva laiendamisfunktsiooniga).<\/p>\n<p>Hiljem selles artiklis jagan, kuidas seda koodi testida, kuid pange t\u00e4hele, et \u00fclaltoodu ei paku mitte ainult teile kuvatavaid funktsioone, vaid ka <strong>taksonoomiaklassi<\/strong> funktsioone .<\/p>\n<h3>Konkreetne taksonoomia: kategooria<\/h3>\n<p>Enne kui hakkan seda tegevuses vaatama, tahan m\u00e4\u00e4ratleda ka kategooria. See h\u00f5lmab koodi, mis rakendab abstraktse klassi funktsioone, aga ka oma funktsioone.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-02-category-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Vaata allpool:<\/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>Siin on meil k\u00f5ik <strong>taksonoomiaklassiga kaasnev<\/strong>, kuid oleme m\u00e4\u00e4ratlenud ka oma atribuudi selle vanema ID ning getter- ja setter-meetodite jaoks. Kuigi antud juhul on see triviaalne, n\u00e4itab see, kuidas kategooriad, mis on hierarhilised, v\u00f5ivad toimida.<\/p>\n<p>Lisaks, kui kategoorias pole vanemat, m\u00e4\u00e4ratakse ID v\u00e4\u00e4rtuseks -1, mis muudab automaatse testimise jaoks lihtsaks kirjutamise v\u00f5i isegi kontrollimise, kas sellel on \u00fclem.<\/p>\n<h3>N\u00e4hes seda tegevuses<\/h3>\n<p>Kogu selle koodi demonstreerimiseks on mul p\u00f5hisisu, mis sisaldab kogu koodi \u00fches failis. Parima tavana ma seda ei soovita. Selle asemel tuleks iga klassi hoida oma failis ja iga klass peaks kuuluma nimeruumi.<\/p>\n<p>Kuid kuna see on puhtalt demonstratsiooni eesm\u00e4rgil, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-03-demo-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">siis sellest piisab.<\/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>Kui k\u00e4ivitate selle konsoolis, peaksite n\u00e4gema j\u00e4rgmist v\u00e4ljundit:<\/p>\n<p>V\u00f5imalik, et peate lisama m\u00f5ned <strong>kajalaused<\/strong>, et veenduda, et see loob uusi ridu, kuid see on teie otsustada.<\/p>\n<h2>Aga liidesed?<\/h2>\n<p>Niisiis, praegusel hetkel:<\/p>\n<ul>\n<li>meil on toimiv m\u00e4\u00e4ratlus selle kohta, mis on abstraktsed klassid,<\/li>\n<li>meil on n\u00e4ide sellest, kuidas abstraktsed klassid v\u00e4lja n\u00e4evad,<\/li>\n<li>ja meil on toimiv demo nende toimimise kohta.<\/li>\n<\/ul>\n<p>J\u00e4rgmisena sukeldun s\u00fcgavamalt abstraktsete klasside ja liideste erinevuste \u00fcle, kui soovite v\u00f5ib-olla kasutada \u00fchte v\u00f5i kui soovite neid kasutada koos \u00fcksteisega.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Abstraheeriv k\u00e4itumine on objektorienteeritud programmeerimisel keskse t\u00e4htsusega, kuid oluline on m\u00f5ista, kuidas seda teha.<\/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":[718,894,916,842,802],"tags":[1165],"class_list":["post-229690","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-arendaja","category-kood","category-muud","category-opetused","category-php-4","tag-affiai-et"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/posts\/229690","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/comments?post=229690"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/posts\/229690\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/media\/164837"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/media?parent=229690"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/categories?post=229690"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/et\/wp-json\/wp\/v2\/tags?post=229690"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}