Moose: Porovnání verzí
KiokuDB |
m link -> Perl |
||
Řádek 1: | Řádek 1: | ||
'''Moose''' je objektový systém, vytvořený jako knihovna v |
'''Moose''' je objektový systém, vytvořený jako knihovna v [[Perl]]u na knihovnou [[Class::MOP]]. V podstatě vytváří určitý způsob myšlení (školu, anticipující [[Perl6]]), jak zacházet s objekty v Perlu (s objekty se zde jinak dá zacházet celkem volně). |
||
== Info == |
== Info == |
||
Řádek 65: | Řádek 65: | ||
* Konkrétní ''instance'' se vytvářejí pomocí konstruktoru ''new'' |
* Konkrétní ''instance'' se vytvářejí pomocí konstruktoru ''new'' |
||
* ''metoda'' je funkce, asociovaná s třídou. Když se volá, má vždy nějaký ''invokant'', se kterým metoda pracuje: |
* ''metoda'' je funkce, asociovaná s třídou. Když se volá, má vždy nějaký ''invokant'', se kterým metoda pracuje: |
||
** když vytváříme nový objekt, je tím invokantem '' |
** když vytváříme nový objekt, je tím invokantem ''jmé |
||
** když voláme metodu u konkrétní instance, je tím invokantem ''tato instance''. |
|||
* ''Invokant'' se v Perlu předává funkci jakožto ''první argument''. |
|||
I když se nejedná o nějaký předpis jazyka Perl, jde o určitou konvenci, že jména tříd začínají velkými písmeny (třída je jakoby větší, protože může mít mnoho instatncí), zatímco jména instancí začínají malými písmeny, tedy je: ''Kocka líza''. (Je to přesně naopak než v češtině, angličtině i jiných jazycích, kde píšeme ''kočka Líza.) Pokud se nám to nelíbí, nemusíme samozřejmě tuto konvenci dodržovat. |
|||
<source lang='perl' line> |
|||
#! /usr/bin/perl |
|||
use Modern::Perl; |
|||
use utf8; |
|||
binmode STDOUT, ':utf8'; |
|||
{ |
|||
package Kocka; |
|||
use Moose; |
|||
sub mňau |
|||
{ |
|||
my $self = shift; |
|||
say 'Mňau!'; |
|||
} |
|||
} |
|||
my $líza = Kocka->new(); |
|||
my $mňouk = Kocka->new(); |
|||
$líza->mňau(); |
|||
$mňouk->mňau(); |
|||
</source> |
|||
*1. Říkáme shellu, který program má interpretovat tento skript. |
|||
*2. Programujeme ve stylu Modern::Perl. |
|||
*4. Co je ve skriptu, bude bráno jako znaky [[UTF-8]] |
|||
*5. Co půjde na standardní výstup, bude chápáno také jako text v UTF-8 |
|||
*7. Začneme nový blok (složená závorka), protože to bude nový balík s vlastním jmenným prostorem. |
|||
*8. Vytvářím ''třídu'' Kocka. |
|||
*9. Používám k tomu knihovnu Moose. (Tím je dané např. i implicitní vytvoření konstruktoru ''new''.) |
|||
*11. Podprogram, přesněji řečeno ''metoda'' mňau, kde říkám, jak má libovolná kočka mňoukat. |
|||
*13. Uložíme invokant (tedy první parametr funkce) do proměnné $self. |
|||
*14. Tady konečně říkám, jak má kočka mňoukat. |
|||
*18.–19. Postupně vytvářím dvě instance koček, tedy dva konkrétní případy, kočky Lízu a Mňouka. |
|||
*21.-22. Vyzkouším si, jak mňoukají. |
|||
Výstup skriptu bude jednoduchý: |
|||
<pre> |
|||
Mňau! |
|||
Mňau! |
|||
</pre> |
|||
Někdo namítne, že je to nedokonalé, že Mňouk je kocour a ten že mňouká jinak. Námitka je na místě, časem zjistíme, že je možno vytvářet i různá pohlaví, která budou mňoukat jinak. |
|||
=== 02. Atributy === |
|||
Když už vytváříme takovéto kočky, bylo by dobré, aby samy kočky věděly, jak se jmenují a mohly se nám na požádání třeba představit. Tedy všechny kočky (tj. třída koček) by měla mít nějaký šuplíček, kam by se ukládalo jméno té které kočky. A pak třeba její věk (kolik je jí let) a jestli třeba nemá nějakou dietu (třeba vytváříme databázi pacientů v kočičí nemocnici). |
|||
Tyto tzv. ''atributy'' (někdy se jim říká ''stav'' anebo prostě data dané instance) se v ''Mose'' přikládají pomocí funkce <tt>has()</tt>; zde je možné rovněž určit, jestli je možné tento atribut dále měnit a jaký typ proměnné bude použit, což představuje určitý typ kontroly nad tím, jak budeme moci s objektem nakládat. |
|||
<source lang='perl' line> |
|||
#! /usr/bin/perl |
|||
use Modern::Perl; |
|||
use utf8; |
|||
binmode STDOUT, ':utf8'; |
|||
{ |
|||
package Kocka; |
|||
use Moose; |
|||
has 'jméno', is=>'ro', isa=>'Str'; |
|||
has 'věk', is=>'rw', isa=>'Int'; |
|||
has 'dieta', is=>'rw'; |
|||
} |
|||
my $tlusťoch = Kocka->new(jméno=>'Tlusťoch', věk=8, dieta=>'produkty moře'); |
|||
say $tlusťoch->jméno(), ', ', $tlusťoch->věk(), ' let, dieta: ', $tlusťoch->dieta(); |
|||
$tlusťoch->dieta( 'neslaná'); |
|||
say $tlusťoch->jméno(), ', ', $tlusťoch->věk(), ' let, nová dieta: ', $tlusťoch->dieta(); |
|||
</source> |
|||
* 11. atribut ''jméno'' je read-only a je to string |
|||
* 12. atribut ''věk'' je read/write a je to číslo |
|||
* 13. atribut ''dieta'' je read/write a není řečeno, jaký typ proměnné to bude |
|||
* 16. vytvoříme tlusťocha, který se jmenuje ''Tlusťoch'', je mu 8 let a má speciální dietu |
|||
* 18. vypíšeme výše zadané informace o tlusťochovi a to pomocí samočinně vytvořených metod (kterým se říká ''akcesory''), které se volají ''bez argumentů'' (prázdné závorky) |
|||
* 20. změníme mu dietu pomocí metody ''dieta'', která se automaticky vytvořila právě z účelem změny atributu; formálně je shodná s akcesorem, akorát že se volá s příslušným argumentem; takové metodě se pak říká ''mutátor'' |
|||
* 21. znovu vypíšeme status |
|||
Výstup programu: |
|||
<pre> |
|||
Tlusťoch, 8 let, dieta: produkty moře |
|||
Tlusťoch, 8 let, nová dieta: neslaná |
|||
</pre> |
|||
=== 03. Enkapsulace === |
|||
Enkapsulace neboli ''zapouzdření'' znamená, že se skryjí vnitřní detaily objektu. |
|||
Příklad: Namísto toho, abychom zadávali věk kočky, zadáme datum jejího narození a její věk se pak automaticky spočítá. Pozměníme třídu Kocka: |
|||
<source lang='perl'> |
|||
{ |
|||
package Kocka; |
|||
use Moose; |
|||
has 'jméno', is=>'ro', isa=>'Str'; |
|||
has 'dieta', is=>'rw'; |
|||
has 'rok_narození', is=>'ro', isa=>'Int'; |
|||
sub věk { |
|||
my $self = shift; |
|||
my $rok = (localtime)[5] + 1900; |
|||
return $rok - $self->rok_narození; |
|||
} |
|||
} |
|||
</source> |
|||
Pomineme, že věk zde počítáme jen přibližně (zanedbáváme datum narození), ale co je důležité: |
|||
# změnil se popis třídy: namísto atributu ''věk'' je zde uložen atribut ''rok narození'' a je definována metoda na výpočet věku |
|||
# způsob volání se přitom ale nezměnil – věk dané kočky zjistíme stejně jako předtím: |
|||
<source lang='perl'> |
|||
say $tlusťoch->věk(); |
|||
</source> |
|||
Tak to je ta enkapsulace: Zatímco se nějaký vnitřní mechanismus třídy změnil, zvenku se to chová stále stejně; při volání metody nás jakoby nemusí zajímat, jak je to uvnitř té třídy zařízeno, že to tak funguje, hlavně, že to funguje. |
|||
Další výhoda takového přístupu je, že si můžeme definovat nějaké defaultní hodnoty, které konstruktor objektu použije v případě, že nějaké atributy nejsou zadány explicitně; například předpokládáme, že zakládáme rodný list kočky a tím pádem můžeme předpokládat, že pokud nezadáme její rok narození, bude se jednat o nynější rok; pak defaultní hodnotu tohoto atributu definujeme např. následovně: |
|||
<source lang='perl'> |
|||
has 'rok_narození', is=>'ro', isa=>'Int', |
|||
default => sub{(localtime)[5] + 1900}; |
|||
</source> |
|||
<source lang='perl'> |
|||
</source> |
|||
[[Kategorie:Perl]] |
Verze z 30. 10. 2012, 14:23
Moose je objektový systém, vytvořený jako knihovna v Perlu na knihovnou Class::MOP. V podstatě vytváří určitý způsob myšlení (školu, anticipující Perl6), jak zacházet s objekty v Perlu (s objekty se zde jinak dá zacházet celkem volně).
Info
Související články
- KiokuDB – persistentní objekty založené na Moose jsou transparentně ukládány pomocí různých databázových backendů
Externí odkazy
- Linuxsoft.cz – Jiří Václavík (2005–2011): 149dílný seriál Perl:
Instalace
Ubuntu
Při výběru balíku libmoose-perl budou nainstalovány i následující balíky:
- libb-hooks-endofscope-perl (verze 0.08-1) bude nainstalován
- libclass-load-xs-perl (verze 0.03-1) bude nainstalován
- libdevel-globaldestruction-perl (verze 0.04-2) bude nainstalován
- libdevel-partialdump-perl (verze 0.15-1) bude nainstalován
- libeval-closure-perl (verze 0.06-1) bude nainstalován
- libmoose-perl (verze 2.0401-1) bude nainstalován
- libnamespace-clean-perl (verze 0.22-1) bude nainstalován
- libsub-exporter-perl (verze 0.982-1) bude nainstalován
- libsub-identify-perl (verze 0.04-1build2) bude nainstalován
- libtask-weaken-perl (verze 1.03-1) bude nainstalován
- libvariable-magic-perl (verze 0.47-1build1) bude nainstalován
Tutoriál
Sytému Moose je věnována kapitola Objects v knize Modern Perl#07. Objekty. Touto kapitolou je inspirován tento tutoriál. Poznamenejme, že direktivami
use utf8;
binmode STDOUT, ':utf8';
můžeme (pro legraci) používat i české názvy proměnných i s diakritikou (pro vážné programování bych to ale asi nedoporučoval).
Z nějakých důvodů to ale s diakritikou nefunguje v případě, že tak nazveme třídu; příkaz
package Kočka
vyvolá chybu:
Kočka is not a module name at /usr/lib/perl5/Class/MOP/Package.pm line 207. BEGIN failed--compilation aborted at ./07.01Kocka.pl line 9.
Nejspíš se jedná o bug – viz Pragmas > utf8 až na konci: Bugs.
01. Konstruktory – stvoření koček
Tak tedy, vytvoříme si třídu koček, které umí mňoukat, a dvě její instance, Lízu a Mňauka, které pak z mňoukání vyzkoušíme. Ale ještě k terminologii, která je v objektovém programování celkem obvyklá:
- Třída je v Perlu v podstatě to samé, co balík. Má to logiku, zpravidla definice tříd jsou i v jiném (např. knihovním) souboru *.pm, ale klidně mohou být i v tom samém souboru. Hlavně to ale znamená, že všechny proměnné tam jsou plně kvalifikované, tj. mají vlastní jmenný prostor, daný názvem třídy.
- Konkrétní instance se vytvářejí pomocí konstruktoru new
- metoda je funkce, asociovaná s třídou. Když se volá, má vždy nějaký invokant, se kterým metoda pracuje:
- když vytváříme nový objekt, je tím invokantem jmé