Přeskočit na hlavní obsah

OOP v PHP 5 - teorie dědičnosti a ORM

Když se vrátím na začátek, kde jsem tvrdil, že objekty jsou jakýsi obal nad procedurálním kódem, tak se musím zamyslet nad tím, jak umožnit, abych nemusel stále dokola zabalovat jednu a tu samou věc. Třídy bych měl vždy navrhovat tak, aby obsahovali jen to nejnutnější a nebyly zbytečně vázany na jiné třídy. Navíc třídy by něměli obsahovat pevnou vazbu na třídy, které jsou navrženy v jiných úrovních.

Příklad:
Do třídy pro zobrazení stromové struktury nebudu cpát třídu, která mi vrací data stromu. Raději ve třídě stromu napíši metodu, která bude umět přijmout data a zobrazit je. Na získání dat vytvořím jinou třídu.
Když budu později potřebovat zobrazit strom s jinými daty, prostě použiji již hotovou třídu stromu, která přijímá data.


Tím dokážu vytvořit znovupoužitelný kód. K tomu, abych mohl takto tvořit třídy, ale musím znát všechny možnosti objektů. Nyní se vratím k další možnosti objektů a tou je dědičnost.

Dědičnost je vlastnost, která mi umožňuje rozšířit třídu a pozměnit její chování. Nic víc, nic míň.

Na začátku jsem napsal, že třídy by měli být co nejořezanější, neměli by obsahovat věci, které by ji svázali natolik, že by obsahovala zbytečné a nevyužitelné vazby. Pokud ovšem v projektu potřebuji danou třídu rozšířít a to tak, že dané rozšíření budu využívat vícekrát, prostě napíši si novou vlastní třídu, která bude dědit vlastnosti z minulé třídy.

Příklad:
Mám třídu na zobrazování filtrace nad daty. Teď je ovšem problém, že v některých případech filtruji přes ty samé položky (př. název). Jednou možností je, pořád do objektu posílat objekt (komponentu) název. Jelikož už vím, co je dědičnost, mohu ji využít. Vytvořím novou třídu, která bude dědit třídu filtrace a navíc bude automaticky vkládat komponentu pro název.


Toto je jedna z možností jak dědičnost využít, přiznávám, že ne moc efektivní, jistě existují i jiné možnosti, ale jako příklad je to postačující.

Asi lepším příkladem je struktura dat v databázi. Dnes jsou nejrozšířenejší relační typy databází. Jistě jsou velmi efektivní, rychlé a snadné na práci, ale pro nás jsou dost nevyhovující, proto existuje ORM (objektově relační mapování), což není nic jiného, než, že tabulku v databázi převedeme na objekt.

CREATE TABLE zamestnanec (
cislo int NOT NULL,
jmeno varchar(100) NOT NULL,
prijmeni varchar(100) NOT NULL,
PRIMARY KEY(cislo)
);



class Zamestnanec {
private $cislo;
private $jmeno;
private $prijmeni;
/* + setry a getry ke vsem atributum */
}


Nyní vytvoříme tabulku "uzivatele". U uživatelů budeme potřebovat navíc heslo, počet přihlášení, poslední přihlášení. V databázi tedy vytvoříme tabulku "uzivatele", která bude mít primární klíč osobní číslo, které bude zároveň cizím klíčem s vazbou do tabulky zaměstnanců na osobní číslo.

Potom pro výpis uživatelů použijeme něco takového:
SELECT u.*, z.jmeno, z.prijmeni
FROM uzivatele u
INNER JOIN zamestnanci z ON u.cislo = z.cislo


To je v pořádku, databázi máme, ale jak to uděláme v našem projektu, kde máme objekty? Velice jednoduše, použijeme dědičnost.

class Uzivatel extends Zamestnanec {
private $heslo;
private $pocetPrihlaseni;
private $posledniPrihlaseni;
/* setry a getry */
}


Nyní jsem vlastně rozšířil zamestnance o další atributy aniž bych musel znovu psát jeho vlastnosti (např. v Jave na toto existují tzv. entity classes, u nich by bylo toto rozdělení více podobné struktuře DB, což v PHP zařídit jen tak nepůjde). Dědičnost se definuje tak, že mám jednoho předka, který obsahuje vlastnosti, které se mi budou hodit i ve třídě, která je dědí. Pokud by se mi stalo to, že budu dědit z třídy, která obsahuje vlastnosti, které nebudu nikdy potřebovat, je dědičnost navržena špatně.

Tento článek berte spíše s nadhledem, opravdu se domnívám, že dědičnost je tak záludná záležitost, že bych se na ni na začátku úplně vykašlal. V pozdějších článcích se k tomto tématu vrátím a ukážu, jak něco takového využít v praxi. Příklady, které jsem zde uvedl nejsou úplně nejtypičtější, ale jistě lepší, než ukázky typu: Matka => Dcera, které postrádají použitelnost v praxi.

Příště už o něčem jednoduchém, viditelnosti a klíčových slovech static, final, apod.

Komentáře

  1. A nemas odzkousene nejake hotove ORM v PHP?

    OdpovědětVymazat
  2. Mám své vlastní :)
    Rád bych ho zde právě předvedl. V PHP toto nelze až ta dobře provozovat, důvody jsou myslím jasné, už z toho důvodu, že není objektově koncipováno.
    Jednou z možností je použití PROPEL, kde lze nalézt jak ORM tak DAO.

    OdpovědětVymazat
  3. V praci take pouzivame vlastni ORM, ale pro soukrome ucely se me nechce psat vlastni.

    Treba by nebylo spatne ten serial koncipovat jako projekt. Das zadani a vypracovavas. Pritom vysvetlujes ruzne veci.

    Nekolikatero knizek jsem takto cetl a bylo to dobre, Drzi to ctenare pri cteni.

    OdpovědětVymazat
  4. Nemas pls na sebe email, rad bych se stebou na necem domluvil. Muj je error414@error414.com

    OdpovědětVymazat
  5. Muj mail je a.dostal[paznak]gmail.com

    OdpovědětVymazat
  6. akova rejpava pripominka :D.

    trida class ma atributy private, a pak ji dedis. Jelikoz mas v te tride i setry a getry tak se k tem vlastnostem dostanes.

    class Zamestnanec {
    private $cislo;
    private $jmeno = 'petr';
    private $prijmeni;


    public function getJmeno(){
    return $this->jmeno;
    }
    }

    class Uzivatel extends Zamestnanec {
    private $heslo;
    private $pocetPrihlase­ni;
    private $posledniPrih­laseni;
    /* setry a getry */
    }

    $p = new Uzivatel();
    echo $p->getJmeno();


    Tohle je v poradku. Ale predstav si ze potrebujes zmenit metodu getJmeno().

    class Zamestnanec {
    private $cislo;
    private $jmeno = 'petr';
    private $prijmeni;


    public function getJmeno(){
    return $this->jmeno;
    }
    }

    class Uzivatel extends Zamestnanec {
    private $heslo;
    private $pocetPrihlase­ni;
    private $posledniPrih­laseni;
    /* setry a getry */

    public function getJmeno(){
    $prefix = "LOD";
    return $prefix.$this->jmeno;
    }
    }

    $p = new Uzivatel();
    echo $p->getJmeno();

    Tohle uz zhavaruje. Podle me je to hodne matouci. Napada me akorat pouzit u setru a geteru pouziti final.


    class Zamestnanec {
    private $cislo;
    private $jmeno = 'petr';
    private $prijmeni;


    final public function getJmeno(){
    return $this->jmeno;
    }
    }

    BTW: PHP ma paradni objektovy model

    OdpovědětVymazat
  7. zdravim, chybi mi tady nejake blizsi popsani fungovani dedicnosti digestore, vezmeme-li v uvahu proceduralni fungovani javy.

    OdpovědětVymazat
  8. Abych řekl pravdu, myslím že znovu definovat proměnné v dědičné třídě se nemusí. Nebo nemám pravdu?
    Příklad:
    class sql {
    var $query;

    function dotaz() {
    return mysql_query($this->query);
    }
    }
    class zkouska extends sql {
    $this->query = "select bla bla bla";
    $this->dotaz();
    }

    OdpovědětVymazat
  9. Petulan javu bych do php nepletl, ale jinak souhlasim.

    OdpovědětVymazat
  10. to error414:
    To, že jsou nastaveny private je správně. Přistupovat k atributům třídy by nemělo být přímé, ale právě přes setry a getry. To co popisuješ bych asi řešil vlastní třídou, jinak stále mám možnost použít přepsání prvotní metody, ale s tím, že musím samozřejmě vytvořit vlastní atribut. Nebo atributy nastavit na protected :)

    to Petulan:
    Jsi to moje chytrá dívka ;)

    OdpovědětVymazat
  11. to JakubVrabec:
    Právě že musí. To, co popisujš ty, je starý kód z PHP4, kde neexistovala viditelnost (private, protected, public), tak jistě setry a getry téměř ztráceli smysl, jelikož to stejně vývojáře tlačilo k použití atributu napřímo.

    class Zvyky {
    private $pozdrav;
    public function __construct() {
    $this->pozdrav = "ahoj";
    }
    }

    class NoveZvyky extends Zvyky {
    public function __construct() {
    parent::__construct();
    // k atributu pozdrav nemam jiz pristup
    echo $this->pozdrav;
    }
    }

    OdpovědětVymazat
  12. Ja bych tam stejne radeji dal jen chrane (protected) abych se vyhnul problemum

    OdpovědětVymazat

Okomentovat

Populární příspěvky z tohoto blogu

Jak si v IT vydělat hodně peněz?

Na začátek by bylo dobré, abych objasnil samotný titulek, který může na někoho působit jako červený hadr. Článek nebude o obecných pravidlech, ale bude vyprávět můj vlastní příběh, na kterém vám zkusím ukázat, jak se dá docílit úspěchu, či alespoň správně nastartovat svojí vlastní kariéru v IT.

I když se z názvu článku dá dedukovat, že se vše bude točit kolem peněz, není tomu tak. Alespoň ze dvou třetin určitě ne. Ale to už předbíhám, pojďme to raději vzít hezky popořadě...

Kdybychom měli mluvit o roce 2017 jako o přelomové době, nejspíše to nebude pravda. I když pro někoho to může být rok plný úspěchů a štěstí v podobě narození zdravých dětí, svatby či první velké lásky, tak z pohledu lidstva se jedná o rok, který jen kopíruje předešlé a v oblasti technologií nás posouvá stejným tempem jako rok předtím.

Jsem naprosto přesvědčen o tom, že i když se současná doba tak nenazývá, tak prožíváme dobu, která jednou bude označena za revoluční, a to zejména díky vynálezu internetu, který je st…

Jak by se firmy neměly chovat k programátorům?

Každý, kdo pracuje v IT oboru, se jistě již setkal s různými „geniálními nápady“, od kterých si firma slibovala zlepšení produktivity či snížení nákladů. Ať už je to zavedení agilních principů, striktní kontrola práce či zavedení nové a skvělé metodiky, o které si „šéf“ přečetl včera na internetu. Jsou z toho skutečně tak nadšení i samotní vývojáři? A bude nový nápad fungovat?
K napsání tohoto článku mě navedly různé programátorské diskuze, kde si lidé stěžovali na firmu, kde pracují. Příklady, které zde uvedu, jsou z reálné praxe. Ať už jsem je zažil jako řadový programátor, či jako šéf týmu.
I když je poptávka po programátorech tak vysoká, že Vás headhunteři nahánějí i ve chvílích, kdy o to opravdu nestojíte, tak i přes to je mnoho lidí, kteří se bojí opustit svoje současné zaměstnání.
Čeho se nejčastěji bojíme? Je to samozřejmě nejistota, kterou si často omlouváme větami jako: „Tady mám své pohodlí, co když to jinde mít nebudu?“ nebo „I když mě to v práci štve a nebaví, tak mě ale…

Jak jsem technologicky postavil startup

Tento příběh pojednává o technologiích, nástrojích a vůbec o všem, co jsem potřeboval k tomu, abych byl schopen, postavit startup na zelené louce.

Každý správný příběh začíná stejně: "Jednou jsem...."

Kapitola první: Nápad
Jednou jsem se setkal s člověkem, který měl nápad na produkt, který se v průmyslu zatím nevyskytuje. I přes prvotní skepsi, kdy jsem si říkal: "Tohle už přeci dávno v průmyslu existuje, ne?", jsem došel ke zjištění, že nikoli.

Tím jsem se dostal ke svému prvnímu poučení. Průmysl je technologicky dost zabržděný. Osobně se domnívám, že těch důvodů, proč tomu tak je, je několik. Za prvé je to fakt, že většina lidí, kteří se pohybují v tomto odvětví jsou často konzervativní a za správné považují pouze léty osvědčené věci. Druhým důvodem je to, že jakákoli změna znamená riziko. Ať už z pohledu finanční ztráty tak i z pohledu stability výroby. No a třetím a nejzásadnějším důvodem je to, že ač zde máme spousty technologických vymožeností, narážíme na to,…