Finální třídy v Nette – proč?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Ondřej Mirtes
Člen | 1536
+
0
-

Ahoj,
už několikrát jsem narazil na toto nepříjemné omezení a chci se zeptat, proč tomu tak je – proč jsou některé třídy v Nette označené jako finální a nelze si je tedy podědit?

Hodilo by se mi např. podědit si Tools, abych pak v kódu nemusel rozlišovat, jestli je daný tool ode mě nebo z Nette – takhle musím přemýšlet, jestli se mám odkazovat na třídu Tools nebo např. MyTools…

Nyní se snažím napsat si skript, který zajišťuje kompatibilitu mezi NPrefixed a non-prefixed verzí Nette, aby člověk při nemilém zjištění, že na serveru běží nějaký HTTP rozšíření, nemusel přepisovat celou svojí aplikaci, ale musel pořešit jen místa, kde se odkazuje přímo na HttpRequest třídu. Nápad je takový (zahlédl jsem ho zde na fóru, psal to myslím Roman Sklenář):

...
class FreezableObject extends NFreezableObject { }
class Image extends NImage { }
class ImageMagick extends NImageMagick { }
class InstanceFilterIterator extends NInstanceFilterIterator { }
...

Jenže ho nelze zrealizovat kvůli tomu, že např. třídy String nebo Environment (na které se člověk v kódu hodně často odkazuje) jsou deklarované jako finální.

redhead
Člen | 1313
+
0
-

Stejnej problém jsem měl při psaní Live Validace, InstantClientScript je taky final :(

Taky by mě zajímalo proč…

Ondřej Mirtes
Člen | 1536
+
0
-

Ať je Davidův úmysl jakkoli správný, je vidět, že to překáží :))

h4kuna
Backer | 740
+
0
-

Taky jsem potreboval podedit tridu SafeStream

Honza Kuchař
Člen | 1662
+
0
-

Ja Ladenku.

paranoiq
Člen | 392
+
0
-

taky Laděnku. vadí to dost

jtousek
Člen | 951
+
0
-

Také laděnku. Neříkám, že je špatně některé třídy zavřít, ale občas je to vážně na obtíž.

sodae
Nette Evangelist | 250
+
0
-

Můžu se zeptat proč tu všichni postujete co vám prostě vadí ? Bud prostě se Davida vyzve k odstranění „problému“ ze všech souborů a bud se tak stane a nebo třeba napíše proč ne.. Takže Davide, bude něco ?

Ondřej Mirtes
Člen | 1536
+
0
-

sodae napsal(a):

Můžu se zeptat proč tu všichni postujete co vám prostě vadí ? Bud prostě se Davida vyzve k odstranění „problému“ ze všech souborů a bud se tak stane a nebo třeba napíše proč ne.. Takže Davide, bude něco ?

Takovou reakci tu od něj přesně čekáme (jiná snad ani neexistuje) a mezitím snad můžeme psát důvody, proč chceme ty final keywords odstranit :)

Ondřej Brejla
Člen | 746
+
0
-

Tím „důvody“ asi myslíš „důvod“, že ;-) Podědit si třídu…:-) Tak Davida zkuste donutit, ať ze stávajících final implementací udělá abstract a teprve z nich třeba prázdné final…a vy si můžete beztrestně dědit abstracty :-D Fuj…to je ale ošklivé řešení…snad ho nebude moc lidí brát vážně ;-)))

David Grudl
Nette Core | 8227
+
0
-

Nette obecně používá přístup „všechno zakázat a povolit až tehdy, když není jiného zbytí“ ;)

Takže je úplné možné, že to překáží, ale v tom případě se stačí ozvat.

No když už se Ondřej ozval, tak mu budu oponovat.

Hodilo by se mi např. podědit si Tools, abych pak v kódu nemusel rozlišovat, jestli je daný tool ode mě nebo z Nette – takhle musím přemýšlet, jestli se mám odkazovat na třídu Tools nebo např. MyTools…

Statické třídy jako Debug nebo Environment jsou final, protože nejsou navrženy k rozšiřování. Pokud by je bylo potřeba rozšířit, chce to otevřít diskusi na fóru a nějak na to třídy připravit.

Statické třídy jako String nebo Tools jsou final, protože fungují jen jako „namespace“ pro funkce. Je otázka, jestli chování, kdy se nemusí rozlišovat „jestli je daný tool ode mě nebo z Nette“ je správné, ale dejme tomu, tady by se asi dalo final zrušit.

Nyní se snažím napsat si skript, který zajišťuje kompatibilitu mezi NPrefixed a non-prefixed verzí Nette…

Porušit objektový návrh, tj. vhodné používání modifikátorů přístupu, kvůli vyloženému hacku, by těžko šlo udělat s čistým svědomím. Nicméně v tomto případě si myslím, že to stejně nemůže 100% fungovat, i kdyby ve frameworku žádné final nebyly.

Ondřej Mirtes
Člen | 1536
+
0
-

Jasně, já na jednu stranu chápu, proč jsou final. Na druhou stranu nijak framework nepoškodí, když si je někdo podědí a bude používat svoji variantu. Ale rozhodně nechci, abys znásilňoval objektový návrh kvůli mým výmyslům :) Ale ostatní tu píšou, že si taky chtějí podědit některé třídy.

Jednoznačná překážka je to ovšem u té kompatibility s NPrefixed verzí. Nebál bych se, že by to nefungovalo – myšlenka je taková, že soubor s potomky všech tříd ti vyřeší 99% kódu a zbylé 1% vyřešíš ručně – např. zakomentuješ class HttpRequest extends NHttpRequest { } a ve svém kódu ručně opravíš místa, kde HttpRequest používáš. (I když si teď uvědomuji, že se většinou bere přes Environment::getHttpRequest() a stačilo by podědit Environment, který je ovšem final, ale to byl jen příklad :))

Píšu si totiž takový „improved Skeleton“, který bude mít navíc spoustu featur, které využívám v každé aplikaci, a chci tam mít pořešené i toto. Nejhorší zjištění je, když zjistím, že na serveru běží HTTP rozšíření, a já kvůli tomu musím hodinu jak opice přidávat Nka do všech zdrojových kódů aplikace :)

v6ak
Člen | 206
+
0
-

Safestream? Co takhle kompozici místo dědičnosti?