PHP v objetí objektů (1)

Michal Burda 16. 7. 2001

V tomto seriálu bych rád objasnil základní principy objektově orientovaného programování, jeho realizace a použití v PHP. Nechci se omezit jen na výklad konstrukce tříd a vytváření objektů, ale rád bych celou tématiku popsal tak, aby neznalý čtenář byl po přečtení schopen objektovou část PHP *skutečně* používat.

K napsání tohoto článku mě přiměla mezera v originální dokumentaci k PHP, kde je práce s objekty popsána jen okrajově a mnoho důležitých faktů v ní není zmíněno vůbec. Také další odborná literatura o PHP, která v České republice vyšla, objektově orientované programování v PHP popisuje jenom povrchně. V tomto seriálu se vám pokusím předat ucelený materiál, abyste celou problematiku bez problémů zvládli a mohli OOP v PHP skutečně uplatnit – nebo přečíst a zavrhnout.

Telegraficky o tom, co nás v tomto a příštích pokračováních čeká:

  1. Co je to OOP
  2. Definice tříd, jejich atributů a metod
  3. Pojednání o konstruktorech
  4. Dědičnost, volání předefinovaných metod
  5. Statická volání metod
  6. Polymorfizmus
  7. Problémy s operátorem přiřazení
  8. …a něco navíc

Chvíli jsem uvažoval, jestli by název tohoto článku neměl raději znít „V PHP obětí objektů“, protože pokusy o objektové programování v PHP vám místy přinesou nejednu pernou chvilku. Jako třeba… Začněme ale pěkně od začátku.

Stručně o objektově orientovaném programování (OOP)

OOP je metoda tvorby programů, která víceméně věrně napodobuje způsob, jakým zacházíme s předměty reálného světa. Tento způsob programování je přehlednější, více strukturovaný, modulárnější a abstraktnější, než klasické procedurální programování.

Objekt je jednoznačně identifikovatelná entita, která má určité vlastnosti (atributy) a chování. Vezměme si třeba obyčejný budík. Jeho vlastnostmi jsou například barva, tvar a druh zvonění. Funkční budík měří čas a ve zvolený okamžik začne zvonit – takové je jeho chování. Každý z nás umí s budíkem zacházet a nikoho už nezajímá, jak uvnitř funguje. Víme, jak z budíku odečíst přesný čas a jak jej nastavit, a to nám stačí k tomu, abychom jej mohli úspěšně používat. OOP ztělesňuje nástroj, kterým lze kód chování „ukrýt“ uvnitř objektu. Až se naučíme definovat třídy objektů, poznáme, že objekty jsou programátorskou konstrukcí sdružující dohromady proměnné (vlastnosti, atributy) a funkce, které s těmito proměnnými pracují (akce, chování). Uživateli objektů stačí znát jenom určité funkce objektu (rozhraní) a o vnitřní implementaci se nemusí starat. Tento koncept je známý pod pojmem zapouzdření: vnitřní implementace mechanismu je oddělena od jeho rozhraní.

Podívejme se na budíky trochu s nadhledem. Všechny plní tutéž úlohu, a přitom se každé jejich provedení tak liší: existují budíky mechanické, elektronické nebo s rádiem, digitální nebo s ručičkama a podobně. Přitom je zřejmé, že jsou si všechny velice podobné. Bavíme se tady o budících, ale každý z nás si představí nějaký jiný. Cítíme, že základní vlastnosti všech budíků světa lze shrnout do abstraktního pojmu „budík“. Každý konkrétní druh je z tohoto abstraktního budíku odvozen – v řeči OOP jaksi dědí všechny vlastnosti abstraktního budíku a staví na nich svá vylepšení.

Přesuňme se teď k programování. Všechny nastíněné principy lze v OOP uplatnit. Objektem je datová struktura se sadou atributů (proměnných) a množstvím funkcí, které s daty pracují. Funkce přiřazené k objektům se v OOP nazývají metody. Data i obslužné metody jsou v objektu zapouzdřeny a navenek ukazují jen svá rozhraní.

Definici objektu je možno zdědit a vytvořit tak nový typ objektu, který může ke stávajícím atributům přidávat nějaké nové vlastnosti, stejně tak jako dodefinovávat (nebo předefinovávat!) zděděné metody. V programech vytváříme rozsáhlou hierarchii příbuzných modulů – objektů. Na vrcholu stromu stojí nejabstraktnější objekt se základními atributy a funkcemi společnými pro všechny. Jeho vlastnosti každý objekt dědí, přidává své atributy a chování – specializuje se až ke konkrétním nástrojům. Výhodami jsou opakovaná použitelnost a přehlednost kódu.

Třídy

Třída je šablonou objektu. Lze si ji představovat jako formičku, do které se „nalejou“ data a vznikne instance (výskyt) objektu.

Abychom mohli vytvářet nějaké objekty, musíme si nejprve připravit patřičné „formy“, tj. třídy. Třída se definuje pomocí příkazu class. V našem příkladu se pokusíme implementovat jednoduché menu. Každá třída musí mít nějaký název, který se píše za klíčové slovo class. Naši třídu nazveme prozaicky „ Menu“:

class Menu {
  # tady budou definice atributů a metod...
} 

Začněme nyní definovat nějaké atributy. Před deklarací vlastnosti se píše klíčové slovo var. Za ním následuje seznam atributů, oddělených čárkou. Proměnným může být rovnou přiřazena hodnota – v takovém případě bude mít každý nový objekt příslušné atributy automaticky inicializovány.

class Menu {
  var $polozky;             # pole položek menu
  var $podklad = '#FFFF00'; # barva pozadí
} 

Zda píšete var před každý název atributu, nebo vlastnosti městnáte za jeden var a identifikátory oddělujete čárkou, je úplně jedno. Vyberte si jeden způsob a ten používejte. Jejich kombinace působí rušivě a přispívá k nepřehlednosti.

Poznámka: Třídy můžete používat také jako obyčejný datový typ záznam (struct v C, record v Pascalu), nadefinujete-li jim jenom atributy, ale žádné metody. Kdo by se ale takto okrádal o sílu OOP?

Pro přístup k atributům objektu se používá operátor ->. Máme-li vytvořen objekt s názvem $moje_menu (jak se ze tříd vyrábějí objekty, se dozvíme příště), který obsahuje atribut $podklad, manipulujeme s ním takto:

Uvedený příklad nejprve do atributu podklad objektu $moje_menu uloží hodnotu #33FF33, a později ji vytiskne na stránku.

Všimněte si, že znak dolaru ( $) se vkládá před název atributu při jeho definici ve třídě (za klíčové slovo var), ale ne při odkazování pomocí operátoru ->.

Poznámka: Samozřejme vám nic nebrání v používání konstrukcí typu:

$promenna = 'pozdrav';
$muj_objekt->$promenna = 'ahoj'; 

Výsledkem bude, že se řetězec „ahoj“ uloží do atributu, jehož název je uchován v proměnné $promenna, tedy do atributu $pozdrav.

Poznámka: Poctivě řečeno, PHP nijak netrvá na deklarování atributů třídy pomocí var. Nové atributy můžete do objektu klidně přidávat „za chodu“. Např. následující kód je úplně v pořádku:

widgety

class MojeTrida {
  var $nazev;
}

/*
... tady se vytvoří objekt moje_trida
podle třídy MojeTrida (jak na to, viz dále)
*/

$moje_trida->nazev = '1.B';
$moje_trida->pocet_zaku = 15;
...
print 'Třída ' . $moje_trida->nazev
    . 'má ' . $moje_trida->pocet_zaku . ' žáků.'; 

Bez jakýchkoliv rozpaků jsem použil nový atribut pocet_zaku a PHP to ochotně zbaští. Chtěl bych vás ale před takovou nedbalostí varovat. Velice to zvyšuje nepřehlednost kódu.

Pokračování příště…

Našli jste v článku chybu?
Lupa.cz: Jak se prodává firma za miliardu?

Jak se prodává firma za miliardu?

Podnikatel.cz: Slevu na dani na EET neuplatní každý

Slevu na dani na EET neuplatní každý

Podnikatel.cz: Babišovi se nedá věřit, stěžovali si hospodští

Babišovi se nedá věřit, stěžovali si hospodští

Vitalia.cz: 5 chyb, které děláme při skladování potravin

5 chyb, které děláme při skladování potravin

Vitalia.cz: Muž, který miluje příliš. Ženám neimponuje

Muž, který miluje příliš. Ženám neimponuje

DigiZone.cz: Parlamentní listy: kde končí PR...

Parlamentní listy: kde končí PR...

Podnikatel.cz: Byla finanční manažerka, teď cvičí jógu

Byla finanční manažerka, teď cvičí jógu

DigiZone.cz: Ginx TV: pořad o počítačových hráčích

Ginx TV: pořad o počítačových hráčích

DigiZone.cz: Samsung EVO-S: novinka pro Skylink

Samsung EVO-S: novinka pro Skylink

Vitalia.cz: Test dětských svačinek: Tyhle ne!

Test dětských svačinek: Tyhle ne!

Vitalia.cz: Tohle jsou nejlepší česká piva podle odborníků

Tohle jsou nejlepší česká piva podle odborníků

Měšec.cz: TEST: Vyzkoušeli jsme pražské taxikáře

TEST: Vyzkoušeli jsme pražské taxikáře

DigiZone.cz: Mordparta: trochu podchlazený 87. revír

Mordparta: trochu podchlazený 87. revír

Vitalia.cz: dTest odhalil ten nejlepší kečup

dTest odhalil ten nejlepší kečup

DigiZone.cz: Digi Slovakia zařazuje stanice SPI

Digi Slovakia zařazuje stanice SPI

DigiZone.cz: Funbox 4K v DVB-T2 má ostrý provoz

Funbox 4K v DVB-T2 má ostrý provoz

Vitalia.cz: Jak Ondra o astma přišel

Jak Ondra o astma přišel

DigiZone.cz: Technisat připravuje trojici DAB

Technisat připravuje trojici DAB

DigiZone.cz: DVB-T2 ověřeno: seznam TV zveřejněn

DVB-T2 ověřeno: seznam TV zveřejněn

120na80.cz: Co je padesátkrát sladší než cukr?

Co je padesátkrát sladší než cukr?