Python
Pythonovský OOP model je zmiešanina z C++ a Moduly 3. V Pythone sú všetky atribúty (premmené objetku) verejné a metódy (funkcie objektu) sú virtuálne. Znamená to, že ich môžeme hocikedy meniť a takisto môžeme hocikedy pridávať nové. Vidíme, že Python je veľmi dynamický jazyk. Pojmy "public", "private" a "protected", známe z C++ neexistujú. Jediný spôsob, ako chrániť dáta sú privátne premenné. Tie sa však dajú tiež meniť (aj keď treba povedať, že ich neúsmyselná zmena je skoro vylúčená). Funkcie a metódy sa nedajú preťažiť. Objekty nemusia nevyhnutne patriť nejakej triede.
Toľko teda stručné zhrunutie OOP vlastností Pythona. Ak potrebujete základné informácie o OOP, odporúčam knížku: "TŘÍDY A OBJEKTY V C++" z vydavateľstva Kopp alebo "Základy objektově orientovaného programovaní" z vydavateľsva Computer Press, ktorá vysvetľuje príklady v jazyku Visual Basic. Knižka "Objektovo-orientovaná tvorba systémov a jazyk C++" z vydavateľsta Perfekt posktytne takisto množstvo užitočných informácii o OOP, je však otázne, či ju ešte budete môcť zohnať.
class kos: def __init__(self, obsah=None): self.obsah=obsah or [] def pridaj(self, polozka): "prida polozku do kosa" self.obsah.append(polozka) def vypis(self): "vypise cely obsah kosa" for polozka in self.obsah: print polozkaAko ste si už určite všimli, trieda v Pythone sa vytvorí kľúčovým slovom class, za ktorým nasleduje meno triedy a dvojbodka. V tele triedy sa nachádzajú jej atribúty a metódy. V prípade triedy kos (má to znamenať kôš) som definoval 3 metódy, pričom neboli definované žiadne atribúty. Prvá metóda __init__ je tzv. konštruktor. Ten sa vykoná automaticky pri odvodení inštancie triedy. Deštruktor (vyvolá sa vždy pri zániku inštancie) by sme vytvorili metódou s menom __del__. Zvyšné 2 metódy tiedy kos pridávajú položku do košika, resp. nám vypíšu jeho obsah. Argument self zodpovedá argumentu this z C++, pomocou neho pristupujeme k ostatným atribútom a metódam triedy. Meno self nie je záväzné (skôr konvenčné), namiesto neho by sa dal použiť ľubovoľný iný identifikátor. Pri volaní metódy sa argument self (alebo jeho ináč pomenovaný ekvivalent) nesmie uvádzať! Toľko teórie, poďme k praktickej stránke veci. Ak vytvoríme inštanciu triedy kos, môžeme ju začať veselo pužívať. Inštancie tried sa v Pythone vytvárajú nasledovne:
>>> trash = kos() #trash je instancia triedy kosSyntax tvorby inštancie je meno_inštancie = trieda(). Syntax volania metód a na manipuláciu atribútov je podobný ako u modulov: inštancia.metóda resp. inštancia.atribút.
>>> trash.pridaj('papier') >>> trash.obsah.append('mys') >>> trash.vypis() papier mys
MenoOdvodenejTriedy(MenoZakladnejTriedy): vyraz1 ... vyrazNPomocou výrazov v tele odvodenej triedy definujeme nové atribúty a metódy. V prípade, že vytvoríme v odvodenej triede atribút/metódu, ktorej meno koliduje s menom atribútu/metódy zo základnej triedy, použije sa meno atribútu/metódy z odvodenej triedy. Vďaka tejto vlastnosti zveľaďujeme a upravujeme základné triedy bez nutnosti vytvárať nové:
class kos2(kos): def vypis(self): "vypise poslednu polozku" if len(self.obsah) > 0: print self.obsah[len(self.obsah)-1] def vyprazdni(self): "vyprazdni obsah kosa" self.obsah=[]V novej triede kos2 nám pribudla metóda vyprazdni a metóda vypis bola modifikovaná tak, aby vypisovala len poslednú položku z koša. Konštruktor (__init__) a metóda pridaj boli zdedené z triedy kos a zostali nezmenené.
>>> trash=kos2() #trash je instancia kos2 >>> trash.pridaj('noviny') >>> trash.pridaj('zosit') >>> trash.vypis() #posledna polozka zosit >>> trash.vyprazdni() >>> trash.vypis() #kos je prazdnyAk odvodzujeme triedu z triedy nejakého modulu, použijeme nasledovný syntax:
MenoOdvodenejTriedy(MenoModulu.MenoZakladnejTriedy): vyraz1 ... vyrazN
MenoOdvodenejTriedy(trieda1, trieda2 ... triedaN): vyraz1 ... vyrazNZrozumiteľne povedané, postupujeme ako pri jednoduchej dedičnosti s tým rozdielom, že v definícii triedy uvádzame viacero základných (rodičovských) tried. Asi ste si už všimli, že u našich dvoch tried (kos, kos2) máme dve rovnomenné metódy vypis. Tu si musíme položiť otázku, ktorá z nich sa použije v odvodenej triede (kos3)? Jedna totiž vypíše obsah celého koša, zatiaľ čo druhá len poslednú položku v koši. Odpoveď na našu otázku znie: V prípade rovnomenných atribútov/metód sa použije atribút/metóda tej triedy, ktorá je v zozname argumentov najviac vľavo. To znamená, že v nižšie uvedenom prípade sa vypíše len posledná položka z koša (metóda pocházda z triedy kos2):
class kos3(kos2, kos): "vylepseny kos" def vyprazdniPridaj(self, polozka): "vyprazdni a prida 1 polozku do kosa" self.vyprazdni() self.pridaj(polozka) def __del__(self): f=open('kos3.txt','w') for a in self.obsah: f.write(a+'\n') f.closeV ďaľšej odvodenej triede (kos3) nám pribudla metóda vyprazdniPridaj, ktorá vyprázdni kôš a pridá doň jednu položku. Zaujímavé na tejto metóde je, že volá dve metódy zo základnej (rodičovskej) triedy. Ďalej vidíme v definícii metódu __del__, ktorá je deštruktor triedy kos3. Ten ukladá obsah koša do súboru kos.txt pri zániku inštancie triedy kos3. Pomocou už dobre známeho atribútu __doc__ pristupujeme k dokumentačnému reťazcu. Ten odvodené triedy nededia (čo je aj napokon aj logické).
>>> trash=kos3() >>> trash.vyprazdniPridaj('zosit') >>> trash.vypis() zosit >>> print trash.__doc__ vylepseny kos
>>> class trieda: ... __a_ = None >>> dir(trieda) ['__doc__', '__module__', '_trieda__a_'] #_trieda__a_ je privatna premmenaZaužívaným spôsobom, ako chrániť atribúty objektov, je používať nejaký systém tvorby identifikátorov. Napr. začať každé slovo v identifikátore veľkým písmenom (PythonJeSuper) alebo oddeľovať podržítkom (vypis_cely_obsah) atď. Záleži len na vás, aký spôsob si vyberiete. Dôležité je, aby ste ho aj skutočne doržiavali.
>>> class auto: ... pass ... >>> audi=auto() #potrebuje instanciu auta >>> audi.farba='cervena' >>> audi.verzia='a4' >>> dir(audi) ['farba', 'verzia']
import time #modul na pracu s casom class casObeda: def __init__(self, hodnota): self.hodnota = hodnota def __str__(self): return 'Ide sa obedovat, je ' + `self.hodnota` + ' hodin!' if time.gmtime(time.time())[3]+1 == 12: #je 12 hodin? raise casObeda, time.gmtime(time.time())[3]+1Ešte mi zostáva spomenúť, že atribút __str__ obsahuje reťazec s chybovou hláškou, ktorá sa vypíše pri vyvolaní výnimky výrazom raise. Aby mohla byť číselná hodnota v atribúte self.hodnota spojená s zvyšným reťazcom, musíme ju uviesť v obrátených úvodzovkách (funkcia str(self.hodnota) by spôsobila to isté).
Želám vám veľa úspešných programov v Pythone.