Je známo, že objekty se do jazyka PHP dostaly spíš jako nezvaní hosté.
Docela příznačným rozdílem mezi jazykem, který byl jako objektový již
navrhován, a jazykem, který se jím stal k velkému překvapení samotných
tvůrců, je v absenci resp. přítomnosti společného předka všech tříd.
Object Pascal deklaruje TObject
, DOT.NET má
System.Object
a v Javě nebo Ruby stojí v hierarchii nejvýše
Object
(je delikátní, že nejzákladnější třída
bývá pojmenována objekt). V PHP nic takového neexistuje.
Základní třída obvykle deklaruje metody pro sebereflexi. Například
metodu vracející název třídy. Je to sice detail, ale vždycky mi připadalo
tuze ošklivé mixovat hezký objektový kód s voláním pro-objektové
funkce get_class
:
$a = $obj->myMethod();
$class = $obj->getClass(); // hezké
$class = get_class($obj); // ošklivé
Nekonzistentní generování chyb
Teď trošku odbočím. Objektový model a vůbec chování jazyka PHP mi v mnoha směrech nevyhovuje. Třeba takový přístup k nedeklarovaným členům. To je téměř vždy známka vážné chyby v programu, způsobené třeba překlepem v kódu. Jenže PHP na ni reaguje značně nekonzistentně:
$obj->undeclared = 1; // projde bez hlášení
echo $obj->undeclared2; // generuje Notice
MyClass::$undeclared = 1; // generuje Fatal error
$obj->undeclared(); // generuje Fatal error
Chyby úrovně Notice patří k těm nejdůležitějším a nesmí se při ladění vypínat. Druhým extrémem je Fatal error, který by se spíš měl jmenovat Fatal disaster. Proč? Protože jej nelze obsloužit uživatelským skriptem. Nemáme možnost vygenerovat zprávu pro uživatele. Ten zírá na prázdnou stránku a netuší, co se děje. A hlavně, PHP nemá ani tolik slušnosti, aby odeslalo HTTP kód 500, takže rozbitou stránku (v nejhorším i s chybovou hláškou) zaindexují vyhledávače. PHP fůůůj!
Velice by se hodilo, kdyby přístup k nedeklarovaným členům vygeneroval výjimku. Takovou, která se nechá probublat až nahoru, kde ji zachytí krizová bariéra a promění v korektní hlášení.
Skvělé „vlastnosti“
Zase odbočím. Termínem property se označují speciální členy tříd, které umožňují pracovat s metodami tak, jako by to byly proměnné. Mám na mysli tzv. gettery a settery:
$obj->caption = 'Hello World';
// přeloží se na $obj->setCaption('Hello World')
echo $obj->caption;
// přeloží se na volání $obj->getCaption();
To je nesmírně šikovná věc. Zvenku to vypadá jako obyčejná proměnná, ale přístup k ní máme plně pod kontrolou. Můžeme validovat vstupy. Můžeme generovat výstupy, až když jsou skutečně potřeba. A navíc, pokud neexistuje setter, tak máme read-only proměnnou, což nelze u obyčejné proměnné zajistit.
Property podporují všechny moderní objektově orientované jazyky, v PHP však nejsou a na jejich brzkou implementaci bych si ani nesázel.
Extension method
Ještě jednou odbočím. Naposled. Fakt.
Novinkou třetí verze C# jsou extension method. Jedná se o obdobu prototypování, které znáte z JavaScriptu nebo Ruby. Umožňují připsat nové metody do již existující třídy (JavaScript a Ruby dovoluje metody nejen připsat, ale i přepsat, což však považuji za zlo).
K čemu je to dobré? Máme třeba třídu List reprezentující seznam
položek, která implementuje metody pro jejich přidávání, rušení a
podobně. Z této třídy je odvozena hierarchie podtříd. V praxi zjistíme,
že by se nám docela hodila metoda List::shuffle()
pro náhodné
zamíchání pořadí položek. Jenže kód třídy List nemůžeme modifikovat
(je třeba součástí cizí knihovny). Vytvořit potomka, který by zmíněnou
metodu měl, také nepomůže, protože bychom museli upravit stávající kód,
co objekty List vytváří. A navíc by to neřešilo absenci metod
v hierarchii tříd z List odvozených.
Řešením je vytvořit samostatnou funkci, které objekt předáme a ona na
něm operaci vykoná. Jen místo $list->suffle()
je třeba volat
Tools::suffleList($list)
.
Extension methods jsou rozšíření jazyka, které doplňování metod do
tříd na ryze syntaktické úrovni umožní. Můžeme v programu psát
$list->suffle()
a interpreter bude tiše volat
Tools::suffleList($list)
.
Nette\Object
Po několika odbočkách jsem zpět u diskutované nejvyšší třídy hierarchie. Myslíte, že něco takového PHP potřebuje? S přihlédnutím k celkové koncepci jazyka bych řekl, že ani ne. Ale co kdyby existence této třídy dokázala vyřešit všechny zde zmíněné problémy a rozšířit objektový model jazyka o property a extension method? V tom případě – sem s ní!
Nette\Object je onen zázračný táta všech objektů (dříve NObject). Nenechte se zmást prefixem, nejde o základní třídu jen pro Nette. Používám ji v Texy, dibi a vůbec ve všech svých aplikacích, u tříd, z nichž lze vytvářet objekty.
Samozřejmostí je podpora sebereflexe:
class MyClass extends Object {}
// včetně jmenného prostoru:
// class MyClass extends Nette\Object
$obj = new MyClass();
$class = $obj->getClass();
$has = $obj->getReflection()->hasMethod('test');
Následuje příklad použití vlastností (property):
class Circle extends Object
{
private $radius;
public function getRadius()
{
return $this->radius;
}
public function setRadius($radius)
{
// validate value
$this->radius = max(0, (float) $radius);
}
public function getArea()
{
return $this->radius * $this->radius * M_PI;
}
}
$circle = new Circle;
$circle->radius = 12; // as $circle->setRadius(12);
echo "Radius: $circle->radius"; // as $circle->getRadius();
echo "Area: $circle->area";
// but $circle->area = XXX; throws Exception
Technickou stránku implementace jsem se snažil co nejlépe promyslet. Špatně navržená cesta by mohla narušit zapouzdření objektu, mohla by veřejně zpřístupnit protected a private metody a podobně. Toho se v případě Nette\Object obávat nemusíte. Property fungují pouze jako syntactic sugar, jako něco, co může zpřehlednit kód a těšit programátora, ale pokud nechcete, tak to používat nemusíte. Proto platí, že
- getter i setter musí být veřejná metoda
- getter je povinný, setter volitelný
- názvy jsou citlivé na velikost písmen (case-sensitive)
Možná vás napadá, jestli i metody sebereflexe lze volat „oslazené“. Jasně:
echo "Class: $obj->class"; // $obj->getClass();
$has = $obj->reflection->hasMethod('test');
A nakonec extension method:
class MyClass extends Object
{
public $a;
public $b;
}
// declare method MyClass::join()
function MyClass_prototype_join(MyClass $_this, $separator)
{
return $_this->a . $separator . $_this->b;
}
echo $obj->join(' ');
I zde jsem uvažoval nad několika způsoby implementace, nakonec jsem zvolil tento vycházející ze zvyklostí JavaScriptu. Deklarace v podobě globální funkce má tu výhodu, že unikátnost je zaručena přímo jazykem a existenci lze ověřovat klasickými prostředky.
Nette\Object kultivuje jazyk
Používám Nette\Object jako předka všech tříd, protože mi to usnadňuje vývoj (překlep vyhodí výjimku atd). Jde o třídu dostatečně transparentní, neměla by způsobovat žádné kolize, proto ji můžete používat také. Cílem článku bylo především poukázat na vyšší standard a nové možnosti využití knihoven Texy, dibi a (brzy již) Nette.
Doplnění: o deset let později
Když jsem před deseti lety psal tento článek, sotva by mě napadlo, že tato třída bude mít smysl ještě dnes. Ale samozřejmě některé věci už jsou jinak.
Ze třídy Nette\Object
se stala traita, což lépe
odpovídá jejímu smyslu. A název se změnil na SmartObject
,
protože slovo Object
už nebude možné používat v PHP
7.2. Tuhle změnu jsme nějakou dobu tušili, proto Nette už od verze
2.4 přestalo třídu Object
používat a nahradilo ji zmíněnou
traitou. Extension method nebo reflexi už nepodporuje a properties vyžadují
uvést je v dokumentačním komentáři. Přesný popis najdete
v dokumentaci.
Komentáře
Lamicz #1
PHP nemá ani tolik slušnosti, aby odeslalo HTTP kód 500…
Hm, tohle mi zrovna přijde rozumný, protože HTTP stavové kódy vyjadřují stav serveru (třeba Apache) a ne stav scriptovacího jazyka, který je pouze jako doplněk. Tohle je IMHO chyba programátora, ne webového serveru, a to by se mělo rozlišit.
rarouš #2
To krásný zlo jde napsat i v C# 2+ :D. Stačí jen zvolit vhodný návrh třídy.
PS. nějak to nezvýrazňuje C# kód :(
rarouš #3
To hlavní bych zapomněl. Gratuluju k Nette, vypadá to zatím slibně.
Jan Tichý #4
K těm extension methods – možná by se pro úplnost slušelo dodat, že aby takto zvenku dodávané nové metody neporušovaly zapouzdřenost, pak musí ve svém kódu volat výhradně veřejné metody a členské proměnné příslušné třídy. Pokud by nějak sahaly do protected či private metod/členů, tak by již byla zapouzdřenost narušena. V případě NObject je toto principiálně zaručeno, takže tam samozřejmě problém není.
Jan Tichý #5
#4 Jane Tichý, A ještě jeden důsledek, pokud tedy platí tento předpoklad, pak nepřítomnost extension methods v jazyce nepředstavuje žádný výraznější problém, protože jakákoliv dodatečná funkčnost se pak dá snadno dodat nějakou samostatnou vedle stojící třídou, které se instance původního objektu předá například jako parametr (bůchví, jak se tenhle design pattern jmenuje :)). Mně osobně přijde dokonce toto řešení bližší, protože mám všude jasně odlišeno, co patří původní třídě a co je dodáno zvenku.
Techi #6
Já bych nedělal z PHP něco co není
To je podobné jako přidat typovou kontrolu pro integer/string atp. Prostě se to neujme…
Místo fce get_class() můžeš klidně použít třídu ReflectionClass() když ti to příjde víc OOP cool
To že zavolání neexistující metody způsobí fatal error → no bože, v ne-interpretovaných jazycích by se kód taky ani nepřeložil. Jestli ti to chování tak vadí, můžeš si do skvělý třídy NObject implemetovat __call() který ti bude fatal error obcházet a pro neznámý metody si vyhodíš třeba jenom warning a všichni budeme spokojený :)
kukulich #7
PHP nemá ani tolik slušnosti, aby odeslalo HTTP kód 500…
Od PHP 5.2.4 by to mělo být jinak: „Changed error handler to send HTTP 500 instead of blank page on PHP errors.“
David Grudl #8
#1 Lamiczi, ještě jednou opakuju, že programátor nemá příležitost chybový kód nebo hlášku odeslat. Kód také nemá rozlišovat, který modul serveru chybu způsobil, jestli jádro Apache nebo interpretr PHP.
#4 Jane Tichý, #5 Jan Tichý přesně tak. Opět se jedná o syntactic sugar, tak je tomu i v C#, jehož třetí verze, která s extension method přišla, je s předchozí binárně kompatibilní. Přidal jsem do článku odstavec, aby to bylo srozumitelnější.
Sám implementaci považuji za takový experiment, uvidíme, jestli to bude užitečné nebo ne. Zatím jsem rozpolcen ;)
#6 Techi, nejsem si jist, co přesně se mi snažíš rozmluvit, ani co by se „mělo chytnout“, ale slow down ;)
#7 kukulichu, tak jsem to vyzkoušel v PHP 5.2.5 a ani ťuk: 200 OK ☹
v6ak #9
„rozbitou stránku (v nejhorším i s chybovou hláškou) zaindexují vyhledávače.“
JJ, CZilla.cz jsem sledoval pomocí Google Alerts a ten mi posílal zásadně chybový hlášky…
„Nekonzistentní generování chyb“
JJ, zajímavý je taky toto:
A_CONSTANT;// E_NOTICE
PDO::A_CONSTANT;//E_ERROR
David Grudl #10
#9 v6aku, Jojo. Ba co hůř, „if (A_CONSTANT) { … }“ se vyhodnotí kladně. To je další důvod proč E_NOTICE považovat za nejdůležitější chybové hlášky.
v6ak #11
BTW: nešlo by to přidávání metod obejít takto?:
// mám třídu pro práci se soubory sb_file a chybí mi metoda doToChar
// tak vytvořím potomka a přidám si ji
class v6_file extends sb_file{
function goToChar($c){…}
}
//někde otvírám soubor, vytvářím původní třídu
$f=new sb_file($inputFile);
// a někde jinde používám metodu nové třídy
v6_file::$f->goToChar(„\n“);
JackeLee #12
Ještě by bylo dobrý, kdyby šlo volat
$object->getParentClass()
namístoget_parent_class($object)
. Vím, že to stačí vylepšit přidáním:David Grudl #13
#12 JackeLee, jasně, to by taky šlo přidat. Rozhoduju se podle toho, jak často se funkce používá. get_parent_class v praxi používám spíš výjimečně, tak mi jako objektový přístup dostačuje
$obj->getReflection()->getParentClass()
(vracíReflectionClass
)Dr.Diesel #14
stdClass ?
https://www.php.net/….classes.php
Teď tě teda moc nechápu, PHP má gettery a settery už celkem dávno …
https://www.php.net/…p5.magic.php
__set() , __get()
Tohle mě osobně třeba přijde ujetý. Vezmi si složitější objekt a máš tam hromady těchhle hovadin, kdy máš v principu vesměs stejně pořád ten samý kód. V PHPku teda takhle:
A k těm extension methods …
Ovšem za předpokladu, ze pracuje s public promennými objektu …
Dr.Diesel #15
Jo a kde je Nette? Je prosinec 😁
David Grudl #16
#14 Dr.Diesle,
pa3k #17
#1 Lamiczi, navyše php nemusí bežať len ako modul Apache, kde má to odoslanie HTTP kódu význam.
rarouš #18
#17 pa3ku, že by zkratka měla opět nový význam? Z PHP se nám vyklubalo PHP a teď teď ho chudáka odtřihnem od serveru, tak z něj bude PHP? 😁
The Zero #19
#18 rarouši, První bylo PHP a ne PHP :)
finc #20
No, docela jsem se u toho pobavil :)
Abych byl uprimny, take jsem sveho casu premyslel nad tim, ze si napisi vlastni „Object“. Jenze, pak jsem od toho upustil, uz jen z duvodu, ze pri napojeni cizich trid, jsem stejne tam, kde jsem byl :)
Jinak u toho object mi shazi nasleduji:
Metoda equals, naprosto zasadni vlastnost. Napr. takovou entitu jako napr. „Zamestnanec“ musim umet porovnavat na urovni samotneho objektu.
Jeste kdyby se dalo nejak vyresit pretypovani aby se dalo pretypovavat a dalo slusne programovat vuci rozhrani.
Jinak s clanem vcelku souhlasim, krome „Extension method“, to me osobne prijde jako slusna prasarna.
V Jave treba existuje pro praci s daty kolekce, jejiz hlavni trida je Collection, dale List, atd.
Pokud chci udelat neco, co neni standardni pro dane rozhrani, resi se to napr tak, ze existuje rohrani (jako pro srovnani prvku podle sveho razeni), ktere je pote pouzito v knihovnich metodach (staticke metody) v tride Collections. Jinymi slovy, pokud chci napr seradit list, tak vytvorim tridu s implementaci srovnani a jako parametr v konstruktoru ji poslu muj list. Cele toto poslu do dane staticke metody, kde se stane to, ze list mam najednou srovnany.
Jde take o to, ze kdyz zacnu do trid cpat vlastni metody, tak tim muzu pekne nabourat samotne API. Muze se mi totiz jednoduse stat, ze zacnu pouzivat knihovnu, ktere neco chybi. Sam si tam metodu dopisi. Jenze pote vyjde nova verze, kde jiz metoda bude implementovana (s vlastni implementaci) a pote budu docela v p…li. Zejmena pokud metoda nebude uplne ekvivalentni…
Ale je to nazor od nazoru :)
ivan_d #21
Co by se stalo (v příkladu radius), kdybych se po nějaké době rozhodl, že budu radius ukládat uvnitř třídy v jiném tvaru (třeba ho v setteru vynásobím dvěma a v getteru vydělím) – vně je vše stejné, ale co metoda getArea()? Zevnitř objektu totiž na atribut radius vidím. Znamená to přepis getArea()?
Je to v tomto případě trochu přitažené za vlasy, ale zanevřel jsem na properties, když jsem na toto narazil (kdybych si jen vzpoměl kde). Řeší to NObject?
koubel #22
Vytvářet takovouto základní třídu je určité z Tvého pohledu OK, nicméně to pak určitým způsobem svazuje všechny komponenty k sobě až moc prostřednictvím NObject, bez něj pak nejede nic.
Při extendovani jakychkoli tříd si pak člověk musí si dávat pozor na spoustu věcí, zejména na implementaci magic method. Tím v podstatě nutíš styl práce s objekty potenciálním vývojářům a to některé může odradit.
Properties se dost špatně dokumentují, ne všechny vývojové
nástroje s nimy umí pracovat tak dobře jako s getry a setry.
Další věc je výkonost, magic metody mají opravdu velkou režii v Zend Engine, proto by to chtělo NObject a NClass
mít v céčku 🙂.
David Grudl #23
#20 finci, s tím vlastně zcela souhlasím. Metody Equals a getHashCode jsem tam dokonce chvíli měl, pak zrušil, možná je opět vrátím, ukáže praxe.
#21 ivan_de, V tomto právě spočívá výhoda properties. Kdyby
$radius
byla veřejná proměnná a ty ses rozhodl změnit její tvar, byl by to velký problém, bylo by třeba změnit věškerý kód, který objekt a proměnnou používá. Naopak s použitím property měníš pouze vnitřní implementaci.#22 kouble, NObject je základní třída pro mé vlastní třídy, jestli ji bude chtít někdo taky tak používat, jeho věc. Jejím smyslem je
get_class
, k volání$obj->getRadius()
…)Nabídnout alternativu neznamená někoho do alternativy nutit.
ivan_d #24
#23 Davide Grudle, Já to právě vidím trochu jako nevýhodu – několikrát jsem zbytečně hledal chybu kvůli opomenutí změnit volání uvnitř třídy. A tak jsem na properties zanevřel. Používám setCosi getCosi, popřípadě zautomatizované přes __call (abych nemusel tupě psát ten nejtriviálněší případ), a mám konvenci – uvnitř tříd si k členským proměným přistupuji přes set/get. Má to i výhodu, že lze (imho elegantně) psát:
`$neco
->setCosi($cosi)
->setCosiJineho($cosiJineho)
->save();
`
David Grudl #25
#24 ivan_de, Rozdíl mezi používám properties a metod getAbc() a setAbc() je pouze v syntaxi. Že mohu místo
$obj->setAbc($val)
napsat$obj->abc = $val
.Vezmu to obecněji. Objekt by nikdy neměl vystavovat své atributy veřejně. Jednak tím porušuje princip zapouzdření, odhaluje implementační detaily a může dojít k jeho nekonzistenci. Tak praví koncept OOP.
Mohlo by se zdát, že veřejné gettery a settery jsou v podstatě jen kompromisem: dál dochází k expozici vznitřní implementace, jen je chráněna konzistence objektu.
Takový předpoklad by platil, pokud by setter a getter představoval pouhý obal nad privátním atributem. Tak tomu ale není. Výhoda metod typu
getAbc()
asetAbc($val)
je v jejich ustálené konvenci, mají stručný název a zřejmou funkci. Jako třeba v případě konvence názvů metodisXyz()
nebohasXyz($val)
. A vůbec není podstatné, jestli operují s privátním atributem $abc, takový atribut nemusí ani existovat.V kvalitním objektovém kódu tedy (elegantní) syntaxi pro přístup k aktributům můžeme používat pouze uvnitř objektů. Což je škoda, jazyk nabízí něco, co pak většinou nelze použít. No a to je právě příležitost si život trošku odladit špetkou syntaktického cukříku. Myšlenka je prostá, co kdybychom všechny volání
$obj->setAbc($val)
mohli zapisovat také jako$obj->abc = $val
atd?V podstatě by bylo hezké, kdyby šlo třeba i
$obj->isValid()
zapisovat jako$obj->valid?
, jenže to v PHP nelze, a především by nešlo o zaběhlou konvencni. Naopak „properties“ zaběhlou konvencí jsou.Shrnuto: jde o eleganci zápisu kódu. Na funkci rostlináře to nemá vliv.
ivan_d #26
#25 Davide Grudle, Jo, to je mi jasné, proto jsem se o to svého času snažil, ale popisované problémy vedli k zavržení – v praxi se mi to neosvědčilo (možná svědomitějším programátorům ano). Jen mě napadlo, jestli to není v NObject nějak přečůrané – dříve jsi operoval s $_property, tak mě zajímalo, jestli tam není podobný trik. Ale jsem rád, že budu dál zastávat funkci rostlináře, předsedo.
john #27
to nobjects mě nalákalo stáhnout si texy! a blíže vše prozkoumat… a mám z toho v hlavě jednu takovou mírně intimní otázku na dgx: to všechno stíháš dělat sám nebo máš ješte někoho, kdo ti semtam hilfne? myslím tím třeba ty grafické ikony nebo flashové animace v adresáři „examples“ u texy… že tam zdá se dokonce zbyl čas i na
SELECT * FROM girls WHERE ...
:-Otexy teda super!!
Dr.Diesel #28
2 dgx: Neodpoveděls na můj dotaz v posledním postu 😁 …
v6ak #29
Já osobně uvažuju, zda do toho jít, ale už to zkouším a vypadá to dobře.
BTW: je proti konceptu OOP mít jednu vlastnost jako skutečnou vlastnost a druhou emulovanou přes gettery a settery? Nechce se mi psát:
I když chápu, že někdy to je více nebo méně nutné. (Např. teď jsem psal obal na tokenizer. /* Tam právě zkouším NObject. */)
Ad konzistence&implementace: Vím, že Zend Framework bývá považován za dobře napsaný, ale toto je fakt hnus:
Navíc právě zde se je problém se zmíněnou konzistencí – stačí napsat logicky vypadající
$event->sendEventNotifications=true;
a mám: Fatal error: Call to a member function getDOM() on a non-object in …\Zend\Gdata\Calendar\EventEntry.php on line 76ivan_d #30
#29 v6aku, ‚je proti konceptu OOP‘ – no někteří správně tvrdí: getters are evil :). OOP to neporušuje – je to jen zpráva, kterou lze zavolat nad objektem. Otázka je (v daném případě), je-li to nejlepší řešení.
V praxi je imho nutné snažit se minimalizovat CELKOVÝ čas vývoje: CELKOVÝ = současný + (teoretický) budoucí. OOP je jen dobrý postup jak si uspořádat věci, aby ten budoucí čas se nepříjemně nezvyšoval. Samo o sobě není samospásné. Když někdo ‚přežene pravidla OOP a architekturu‘ je to na pytel.
Michal Aichinger #31
#25 Davide Grudle,
DGX: Rozdíl mezi používám properties a metod getAbc() a setAbc() je pouze v syntaxi. Že mohu místo
$obj->setAbc($val)
napsat$obj->abc = $val
.Tak nějak tu zapomínáme na jednu zásadní věc co odlišuje PHP od např. C#. A to je vývojové prostředí. Jelikož C# podporuje properties, tím pádem to podporuje i VS a tím pádem i VS ví jaké typy to vrací a může nabízet pomocí Code Assist metody toho vráceného objektu.
Tohle v PHP IDEs nelze. Takže pokud používáte např. Prado, které je tímto prolezlé, pak víte, že tam něco je, něco je vám vráceno, ale co to je musíte zjistit buď v paměti, nebo dokumentaci a pak si napsat komentář /*@var $object MyClass*/ , aby vám IDE nabízelo metody objektu. Pokud bude mít zase jen magické nabídne prd.
Kdo používá IDE, nepotřebuje moc magické metody, protože se většinou nepřepíše do blbého názvu 😉
ad ExtensionMethod:
No v JS a Ruby to má to kouzlo právě proto, že lze modifikovat přes prototype právě tu „třídu“ originální a měnit její chování a ne ji rozšiřovat, to je dost o ničem. Většinou je to tak, že když člověk chce přidat funkčnost (shuffle) tak si to podědí a ve svém kódu to použije poděděný. V cizím kódu se ta poděděná metoda stejně nevyužije. V JS a Ruby má právě kouzlo to, že můžeme ovlivnit i chování těch částí do kterých nemůžeme jinak zasáhnout.
David Grudl #32
#31 Michale Aichingere, řešením je zatlačit na vývojáře IDE, aby zaimplementovali podporu pro @property (vlastně tímto čtenáře vyzývám – napište jim!). Případně je možné použít tento postup, ale to už s NObject nesouvisí.
ad extension method: chtěl byste OS, kde by ostatní mohli měnit obsah vašich souborů, ač k nim nemají přístupová práva? Někdo tomu říká kouzelné, já tomu říkám vadné…
Petr Staly #33
Pseudo-objekty v PHP sux, Java/C++ rulez ! 🙂
ivan_d #34
#32 Davide Grudle, ‚chtěl byste OS, kde by ostatní mohli měnit obsah vašich souborů, ač k nim nemají přístupová práva?‘ – tak to trochu kulhá – nechtěl bych takový OS, protože někdo jiný by mohl poškodit moje zájmy. Kód nemá svoje zájmy. Ty má pouze programátor. Co může být v 99% případů užitečné vedení, může být v 1% diktát zabedněnce. Ten, kdo užívá můj kód, může být totiž klidně chytřejší než já.
Milan Svoboda #35
#34 ivan_de, To že někdo chytřejší používá můj kód ještě nutně neznamená, že musí přepisovat přímo moje funkce. Protože si pak může stáhnou aplikaci od někoho třetího využívající mého kódu nechá si na webu své upravené knihovny a bude se jen divit, že mu to nefunguje (resp. vetšinou to postihne nějakého zákazníka.). Je to podobný případ jako v javascriptu přpisování prototype. Mně to funguje a že ostatním ne to je jejich problém že 🙂
ivan_d #36
#35 Milane Svobodo, ‚pak může stáhnou aplikaci od někoho třetího využívající mého kódu nechá si na webu své upravené knihovny‘ – kdo to dává dohromady snad ví co dělá a když ne, ať to nedělá. Otázka je, co má člověk ve své kompetenci – zda celek nebo jen část celku, která musí respektovat ostatní. Mluvil jsem o někom chytřejším, ne namyšlenějším.
Mimochodem proč hned myslet na zásadně jiné chování – změněná metoda může jen obalit původní (a třeba přidat log volání).
Washo #37
Muzu se zeptat k cemu slouzi ta getReflection resp. sebereflexe jako takova? Je to pro zjistovani toho jestli lze na danem objektu volat konkretni metodu nebo jeste k necemu?
Diky.
David Grudl #38
#37 Washo, slouží ke kompletnímu prozkoumání objektu – jaké má metody, jaké mají parametry, ve kterém souboru a na kterém řádku jsou definované a spousta dalších vyčerpávajících informací. Viz Reflection v PHP.
David Grudl #39
#7 kukulichu, tak oprava: PHP 5.2.4 mi už skutečně háže HTTP 500.
ivan_d #40
#37 Washo, Příklad – představ si modifikovaného taťku všech objektů, který bude přes __call poskytovat automaticky ke všem atributům settery a gettery – zjistí si v __call přes Reflection, jestli název metody může odpovídat atributu. Pro prskaly – taťka umožní potomku nadeklarovat konzervativní nebo liberální chováni :)
class Person extends NObject{protected $accessMode = NObject::CONSERVATIVE;
protected $attrAccess = 'cosi';
protected $name = '';
protected $surname = '';
protected $cosi = '';
public function __construct($name, $surname){
$this->name = $name;
$this->surname = $surname;
}
}
$franc = new Person('Franc', 'Josef');
$franc->setCosi('cosi');
$franc->setName('Karl'); #exception
#nebo
class Person extends NObject{
protected $accessMode = NObject::LIBERAL;#default
protected $name = '';
protected $surname = '';
}
$franc = new Person;
$franc->setName('Franc')->setSurname('Josef');
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.