{"id":230258,"date":"2022-11-22T11:40:00","date_gmt":"2022-11-22T08:40:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230258"},"modified":"2022-11-22T11:40:54","modified_gmt":"2022-11-22T08:40:54","slug":"abstract-classes-osa-1-abstraktiokaeyttaeytyminen","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fi\/abstract-classes-osa-1-abstraktiokaeyttaeytyminen\/","title":{"rendered":"Abstract Classes, Osa 1 &#8211; Abstraktiok\u00e4ytt\u00e4ytyminen"},"content":{"rendered":"\n<p>Noin kuukausi sitten <a href=\"https:\/\/wordpress.mediadoma.com\/fi\/oop-n-kaksi-ensimmaeistae-pilaria\/\" title=\"kirjoitin yhdest\u00e4\">kirjoitin yhdest\u00e4<\/a> olioohjelmoinnin pilareista (erityisesti abstraktio). Viestiss\u00e4 m\u00e4\u00e4ritin abstraktion seuraavasti:<\/p>\n<blockquote>\n<p>Sen sijaan aiomme ottaa ideoita heid\u00e4n luokkiinsa. Ja t\u00e4ss\u00e4 on keskeinen ajatus: Luokan tulee edustaa substantiivia.<\/p>\n<\/blockquote>\n<p>Ja vaikka se on edelleen totta, <strong>abstraktien luokkien<\/strong> idea on jotain erilaista olioohjelmoinnissa.<\/p>\n<p>Kuulostaa h\u00e4mment\u00e4v\u00e4lt\u00e4, eik\u00f6? Tuo on:<\/p>\n<ul>\n<li>yhdell\u00e4 tasolla meill\u00e4 on abstraktio, joka m\u00e4\u00e4ritell\u00e4\u00e4n ajatukseksi, ett\u00e4 otamme idean ja edustamme sit\u00e4 luokassa,<\/li>\n<li>toisella tasolla meill\u00e4 on abstrakteja luokkia, joita k\u00e4ytet\u00e4\u00e4n auttamaan m\u00e4\u00e4ritt\u00e4m\u00e4\u00e4n toimintoja, jotka alaluokkien on toteutettava.<\/li>\n<\/ul>\n<p>Ja jos se ei ole tarpeeksi h\u00e4mment\u00e4v\u00e4\u00e4, yhdist\u00e4mme t\u00e4m\u00e4n <a href=\"https:\/\/wordpress.mediadoma.com\/fi\/olio-ohjelmointi-kaeyttoeliittymien-ymmaertaeminen\/\" title=\"rajapintoihin\">rajapintoihin<\/a>, jotka tarjoavat sopimuksen toteutusluokkien on seurattava, ja sitten yhdist\u00e4mme sen abstrakteihin luokkiin, jotka m\u00e4\u00e4rittelev\u00e4t menetelmi\u00e4, jotka on my\u00f6s toteutettava, mutta jotka voivat my\u00f6s toteuttaa omia menetelmi\u00e4\u00e4n.<\/p>\n<p>Oletko viel\u00e4 h\u00e4mmentynyt? Ei huolia. Seuraavien kolmen postauksen tarkoitus on tehd\u00e4 seuraava:<\/p>\n<ol>\n<li>M\u00e4\u00e4rittele mit\u00e4 abstraktit luokat ovat,<\/li>\n<li>Kuvaile erilaisia \u200b\u200babstrakteja luokkia ja k\u00e4ytt\u00f6liittymi\u00e4,<\/li>\n<li>Auta p\u00e4\u00e4tt\u00e4m\u00e4\u00e4n, milloin haluat k\u00e4ytt\u00e4\u00e4 toista.<\/li>\n<\/ol>\n<p>T\u00e4ss\u00e4 on koko idea abstraktien luokkien takana.<\/p>\n<h2>Abstrahoiva k\u00e4ytt\u00e4ytyminen<\/h2>\n<p>Ensinn\u00e4kin abstraktioissa ja abstrakteissa luokissa on ero. Edellinen viittaa ajatukseen esitt\u00e4\u00e4 jotain ohjelmoinnissa; j\u00e4lkimm\u00e4inen viittaa todelliseen tapaan kirjoittaa koodia.<\/p>\n<p>Ja yksi parhaista tavoista, joita olen l\u00f6yt\u00e4nyt abstraktien luokkien ajattelemiseen olioohjelmoinnissa, on ajatella niit\u00e4 n\u00e4in:<\/p>\n<blockquote>\n<p>Abstraktit luokat korvaavat toteutuksen.<\/p>\n<\/blockquote>\n<p>Ehk\u00e4 toinen tapa ajatella niit\u00e4 ovat paikkamerkit. Viime k\u00e4dess\u00e4 ne tarjoavat k\u00e4ytt\u00e4ytymisen, joka alaluokkien on toteutettava.<\/p>\n<p>Miten t\u00e4m\u00e4 eroaa k\u00e4ytt\u00f6liittym\u00e4st\u00e4? Muista, ett\u00e4 k\u00e4ytt\u00f6liittym\u00e4 m\u00e4\u00e4rittelee funktiolle allekirjoituksen (funktion nimi, sen argumentit ja sen n\u00e4kyvyysmuuntimet), joka luokan on toteutettava.<\/p>\n<p>Abstraktio puolestaan \u200b\u200b\u200b\u200bkorvaa toteutukselle, joka alaluokan on toteutettava. Mutta ehk\u00e4 t\u00e4m\u00e4 n\u00e4kyy parhaiten koodin avulla.<\/p>\n<h3>Abstraktio k\u00e4yt\u00e4nn\u00f6ss\u00e4<\/h3>\n<p>Oletetaan, ett\u00e4 ty\u00f6skentelet projektin parissa ja huomaat, ett\u00e4 sinulla on toimintoja, joita on useammassa kuin yhdess\u00e4 paikassa. Sen lis\u00e4ksi, ett\u00e4 se rikkoo koko DRY-ideaa, se voi my\u00f6s olla paikka, jossa voit abstrakti toiminnallisuuden perusluokkaan ja k\u00e4ytt\u00e4\u00e4 sit\u00e4 uudelleen.<\/p>\n<p>Tarkastellaanpa t\u00e4t\u00e4 julkaisuj\u00e4rjestelm\u00e4n yhteydess\u00e4. WordPress ei v\u00e4ltt\u00e4m\u00e4tt\u00e4 toteuta sit\u00e4 t\u00e4ll\u00e4 tavalla, mutta se k\u00e4ytt\u00e4\u00e4 meille tuttua ideaa: Taksonomiat.<\/p>\n<p>Muista, ett\u00e4 WordPressiss\u00e4 on <strong>tunnisteita<\/strong> ja <strong>luokkia<\/strong>. N\u00e4iden kahden v\u00e4lill\u00e4 on hienoisia eroja (kuten hierarkkinen vai ei), mutta niill\u00e4 on my\u00f6s samanlaisia \u200b\u200bominaisuuksia, kuten nimi ja etana.<\/p>\n<h3>Taksonomian abstraktio<\/h3>\n<p>Joten voimme aloittaa kirjoittamalla abstraktin taksonomialuokan, joka abstrahoi yhteisen toiminnallisuuden <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-00-taxonomy-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">omaan luokkaansa.<\/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>Yll\u00e4 olevasta koodista n\u00e4et, ett\u00e4 olen tehnyt seuraavat:<\/p>\n<ul>\n<li>julisti luokan <strong>abstraktiksi<\/strong><\/li>\n<li>m\u00e4\u00e4ritt\u00e4nyt useita attribuutteja, jotka asetetaan rakentajassa<\/li>\n<li>toteutti useita julkisia teht\u00e4vi\u00e4,<\/li>\n<li>lis\u00e4tty useita suojattuja menetelmi\u00e4.<\/li>\n<\/ul>\n<p>Keskeinen poikkeama t\u00e4m\u00e4n luokan tarkastelusta on, ett\u00e4 kaikilla luokilla, jotka toteuttavat t\u00e4m\u00e4n abstraktin luokan, on automaattisesti konstruktorissa m\u00e4\u00e4ritetyt toiminnot, <strong>getName<\/strong> -funktio ja <strong>getSlug-<\/strong> funktio.<\/p>\n<p>Niill\u00e4 ei kuitenkaan ole <strong>abstraktien<\/strong> funktioiden toteutusta. Ne j\u00e4\u00e4v\u00e4t alaluokkien toteuttamaan (jotka jaan hetken).<\/p>\n<h3>Konkreettinen taksonomia: tunniste<\/h3>\n<p>Nyt kun meill\u00e4 on m\u00e4\u00e4ritelty abstrakti luokka, on mahdollista todella toteuttaa abstraktio. <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-01-tag-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Esimerkiksi<\/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>Huomaa yll\u00e4 olevassa koodissa, ett\u00e4 luokka tekee vain toteutuksen abstraktissa luokassa m\u00e4\u00e4ritellyille abstrakteille funktioille (joka on m\u00e4\u00e4ritelty <strong>luokan<\/strong> m\u00e4\u00e4ritelm\u00e4n laajennusfunktiolla).<\/p>\n<p>My\u00f6hemmin t\u00e4ss\u00e4 artikkelissa kerron, kuinka t\u00e4t\u00e4 koodia testataan, mutta huomaa, ett\u00e4 yll\u00e4 oleva ei tarjoa vain n\u00e4kem\u00e4si toiminnallisuutta, vaan my\u00f6s <strong>taksonomia<\/strong> &#8211; luokan toimintoja.<\/p>\n<h3>Konkreettinen taksonomia: luokka<\/h3>\n<p>Ennen kuin tarkastelen t\u00e4t\u00e4 k\u00e4yt\u00e4nn\u00f6ss\u00e4, haluan my\u00f6s m\u00e4\u00e4ritell\u00e4 luokan. T\u00e4m\u00e4 sis\u00e4lt\u00e4\u00e4 koodin, joka toteuttaa abstraktin luokan funktioita, mutta my\u00f6s omia toimintojaan.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-02-category-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Katso alempaa:<\/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><strong>T\u00e4\u00e4ll\u00e4 meill\u00e4 on kaikki Taksonomia<\/strong> -luokan mukana tuleva, mutta olemme my\u00f6s m\u00e4\u00e4ritt\u00e4neet omaisuutemme sen yl\u00e4tunnisteelle sek\u00e4 getter- ja setter-menetelmille. Vaikka se on t\u00e4ss\u00e4 tapauksessa triviaalia, se osoittaa, kuinka hierarkkiset kategoriat voivat toimia.<\/p>\n<p>Lis\u00e4ksi, jos luokalla ei ole yl\u00e4luokkaa, tunnukseksi asetetaan -1, mik\u00e4 helpottaa kirjoittamista automaattista testausta varten tai jopa tarkistaa, onko sill\u00e4 yl\u00e4luokkaa.<\/p>\n<h3>Sen n\u00e4keminen toiminnassa<\/h3>\n<p>Koko koodin esittely\u00e4 varten minulla on sis\u00e4lt\u00f6, joka sis\u00e4lt\u00e4\u00e4 kaiken koodin yhdess\u00e4 tiedostossa. Parhaana k\u00e4yt\u00e4nt\u00f6n\u00e4 en suosittele t\u00e4t\u00e4. Sen sijaan jokainen luokka tulisi s\u00e4ilytt\u00e4\u00e4 omassa tiedostossaan ja jokaisen luokan tulee kuulua nimiavaruuteen.<\/p>\n<p>Mutta koska t\u00e4m\u00e4 on puhtaasti esittelytarkoituksessa, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/5b2936875807f041e98a87f8a5627e8b#file-03-demo-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">se riitt\u00e4\u00e4.<\/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>Kun suoritat t\u00e4m\u00e4n konsolissa, sinun pit\u00e4isi n\u00e4hd\u00e4 seuraavanlainen tulos:<\/p>\n<p>Saatat joutua lis\u00e4\u00e4m\u00e4\u00e4n muutamia <strong>kaikulauseita<\/strong> varmistaaksesi, ett\u00e4 se luo uusia rivej\u00e4, mutta se on sinun.<\/p>\n<h2>Ent\u00e4 k\u00e4ytt\u00f6liittym\u00e4t?<\/h2>\n<p>Eli t\u00e4ss\u00e4 vaiheessa:<\/p>\n<ul>\n<li>meill\u00e4 on toimiva m\u00e4\u00e4ritelm\u00e4 siit\u00e4, mit\u00e4 abstraktit luokat ovat,<\/li>\n<li>meill\u00e4 on esimerkki siit\u00e4, milt\u00e4 abstraktit luokat n\u00e4ytt\u00e4v\u00e4t,<\/li>\n<li>ja meill\u00e4 on toimiva demo niiden suorituskyvyst\u00e4.<\/li>\n<\/ul>\n<p>Seuraavaksi sukeltan syvemm\u00e4lle abstraktien luokkien ja k\u00e4ytt\u00f6liittymien v\u00e4listen erojen k\u00e4sittelyyn, milloin saatat haluta k\u00e4ytt\u00e4\u00e4 toista p\u00e4\u00e4llekk\u00e4in tai milloin haluat k\u00e4ytt\u00e4\u00e4 niit\u00e4 yhdess\u00e4 toistensa kanssa.<\/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>Abstraktiok\u00e4ytt\u00e4ytyminen on keskeist\u00e4 olioohjelmoinnissa, mutta sen ymm\u00e4rt\u00e4minen on t\u00e4rke\u00e4\u00e4.<\/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":[719,895,917,843,803],"tags":[1166],"class_list":["post-230258","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kehittaejae","category-koodi","category-muut","category-opetusohjelmia","category-php-5","tag-affiai-fi"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts\/230258","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/comments?post=230258"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts\/230258\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/media\/164837"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/media?parent=230258"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/categories?post=230258"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/tags?post=230258"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}