Omezená dědičnost (je něco lepšího než OOP?)

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #15 kdy: 31. 08. 2015, 15:38:49 »
Short answer: Protocol-oriented programming: http://babel.blog.root.cz/2015/08/25/post-oop/

Long answer: Koncepční vztahy se deklarují pomocí protokolů. Např. každý tenzor je matice (ale ne naopak), každý vektor je tenzor a každý skalár je taky tenzor - jenže skalár je normální double (nebo komplexní číslo) a to už každý jazyk má a nedá se jim "podstrčit" nějaká nadtřída. Dá se ale říct, že vyhovují nějakému protokolu (a dodefinovat příslušné metody, např. pro derivaci tenzorových polí). Druhou výhodou je, že pak lze použít hodnotové typy, které z principu netvoří hierarchie (na rozdíl od tříd), ale zase program zrychlují. Sečteno a podtrženo: dědičnosti je lepší se úplně vyhnout.

Perfekní rozbor, ale bohužel chybný závěr. Hodnotové typy do OOP nepatří. Jsou tam jen proto, že je programátoři chtěli.

Protocol-oriented programming není OOP. Problém je, že žádný jazyk ho plně nepodporuje. Hodnotové typy jsou ortogonální koncept umožňující rychlejší a spolehlivější správu paměti (jako v C++, kde ovšem každý může rozhodnout pro každý objekt, chce-li ho mít na zásobníku).


k

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #16 kdy: 31. 08. 2015, 15:41:34 »
Jaké vztahy na tom chceš hledat? Chceš mi snad tvrdit, že čtverec je obdélník, lichoběžník nebo kosočtverec? Nebo že čtverec obdélník, lichoběžník nebo kosočtverec? Nic z toho není pravda, nemůžeš tedy použít ani dědičnost, ani kompozici.

Potřebujeme vědět co tazatel chce dělat.
O tom co mohu použít naštěstí nerozhoduješ ty, to by byla škoda, také netuším ze kterého klobouku a proč do toho taháš pojmy jako je a :) Na tak triviální věc v 2D stačí společný předek ÜberQuadrat s členskými proměnnými bod, 2x délka, 2x úhel, rotace. Řešení je více, více variant, i pro 3D.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #17 kdy: 31. 08. 2015, 15:42:40 »
Každý čtverec je obdélník.

Není - on tak jen vypadá. Čtverec má jeden atribut, obdélník má dva. 1 != 2.

Jasně, že je. Počet atributů s tím nemá co dělat. https://cs.wikipedia.org/wiki/Čtyřúheln%C3%ADk

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #18 kdy: 31. 08. 2015, 15:46:53 »
stvorec extends obdlznik je standardny fail lebo liskov substitutuion principle

liskova obecne zamita jenom obracenou variantu. Tahle varianta muze a nemusi byt v pohode. Pokud delas imutable objekty, tak v pohode (Z hlediska liskove) je.

Obdelnik(a,b)
a
Ctverec(a)=Obdelnik(a,a)

je z tohohle uhlu pohledu v OK. (Neni to uplne stastny napad trebas protoze ukladas jednu vec dvakrat a neumis moc postihnout nejake invarianty, ale to s liskovou nesouvisi)

Filip Jirsák nepřihlášený

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #19 kdy: 31. 08. 2015, 15:49:12 »
Každý čtverec je obdélník.

Není - on tak jen vypadá. Čtverec má jeden atribut, obdélník má dva. 1 != 2.
V reálném světě ovšem čtverec je speciální případ obdélníku, který má všechny čtyři strany stejně dlouhé. To, že běžné OOP jazyky mají atributy a umožňují je při dědění pouze přidávat, je jejich omezení, a teprve toto omezení vede na to, že se hierarchie udělá opačně, tj. obdélník je rozšíření čtverce. Navíc pokud použijete správně zapouzdření, nebudou vám vadit ani ty atributy, protože čtverec naimplementujete tak, že nastavením jednoho rozměru změníte i druhý, a zbytek už bude fungovat jako speciální případ obdélníku.


Radek Miček

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #20 kdy: 31. 08. 2015, 15:50:50 »
Každý čtverec je obdélník.

Není - on tak jen vypadá. Čtverec má jeden atribut, obdélník má dva. 1 != 2.

Doporučuji zopakovat základy geometrie.

stvorec extends obdlznik je standardny fail lebo liskov substitutuion principle

V LSP záleží na tom, jaké rozhraní třídy mají (nejen typy, ale i jak je definována činnost metod). Tj. LSP nijak nebrání například napsat, že Pes je podtyp Kniha, když rozhraní budou prázdná a objekty nebudou nic dělat.

Kit

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #21 kdy: 31. 08. 2015, 15:56:39 »
... také netuším ze kterého klobouku a proč do toho taháš pojmy jako je a ...

Tato dvě pomocná slovesa jsou významnou a přitom jednoduchou pomůckou při rozhodování, zda použít dědičnost či kompozici. Ještě mě nezklamala.

JSH

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #22 kdy: 31. 08. 2015, 16:02:34 »
Přijde mi že skoro všechny matematické objekty "dědí" způsobem, že se přidávají nějaké podmínky a ubývají stupně volnosti. Naproti tomu běžné dědění umí stupně volnosti spíš přidávat a přidávání podmínek jde taky dost blbě. Minimálně pokud ten objekt není invariantní. I u reálných objektů mi přijde, že vztah je spíš přidává další a další omezení.

Na tohle mi daleko víc pasují classy v Haskellu. Čtverec je immutable, takže se nedá rozbít i když se s ním pracuje jako s obdélníkem. Classy nemají žádná data ale jenom "metody" respektive funkce. V podstatě je to dědičnost omezená na interfacy.

Jak nad tím tak přemýšlím, tak v C++ už dlouho používám public dědičnost jen pro abstraktní třídy (interfacy) a privátní dědičnost jako implementační hack.

k

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #23 kdy: 31. 08. 2015, 16:09:22 »
Tato dvě pomocná slovesa jsou významnou a přitom jednoduchou pomůckou při rozhodování, zda použít dědičnost či kompozici. Ještě mě nezklamala.

No tak právě teď tento postup selhal :) Čtverec, Obdélník, Kosočtverec i Lichoběžník jsou všichni potomci ÜberQuadrat :)

Radek Miček

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #24 kdy: 31. 08. 2015, 16:13:28 »
... také netuším ze kterého klobouku a proč do toho taháš pojmy jako je a ...

Tato dvě pomocná slovesa jsou významnou a přitom jednoduchou pomůckou při rozhodování, zda použít dědičnost či kompozici. Ještě mě nezklamala.

To je obecně špatný přístup. Dědičnost totiž není o podtypech, ale o opakovaném využití kódu. Klasický příklad, kdy děděním nevznikají podtypy, jsou tzv. binární metody.

Při rozhodování, zda je něco podtyp, je lepší použít plný LSP:

If for each object o1 of type S there is another object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2, then S is a subtype of T.

Mj. je vidět, že například reflexe může zneplatnit LSP - typy T a S lze rozlišit reflexí.

Kit

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #25 kdy: 31. 08. 2015, 16:15:33 »
Každý čtverec je obdélník.

Není - on tak jen vypadá. Čtverec má jeden atribut, obdélník má dva. 1 != 2.
V reálném světě ovšem čtverec je speciální případ obdélníku, který má všechny čtyři strany stejně dlouhé. To, že běžné OOP jazyky mají atributy a umožňují je při dědění pouze přidávat, je jejich omezení, a teprve toto omezení vede na to, že se hierarchie udělá opačně, tj. obdélník je rozšíření čtverce. Navíc pokud použijete správně zapouzdření, nebudou vám vadit ani ty atributy, protože čtverec naimplementujete tak, že nastavením jednoho rozměru změníte i druhý, a zbytek už bude fungovat jako speciální případ obdélníku.

Hezké ... ale k čemu je to dobré? Na jednu stranu čtu, že se někdo vyhýbá dědičnosti jako čert kříži, z druhé strany mi zase někdo vnucuje čtverec jako potomka obdélníku. Nevidím důvod, proč bych měl zavádět dědičnost mezi třídami, u kterých jsou pochybnosti o paternitě a dokonce ani není problém vytvořit nového (abstraktního) předka či rozhraní pro všechny zmíněné třídy.

JSH

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #26 kdy: 31. 08. 2015, 16:18:26 »
V reálném světě ovšem čtverec je speciální případ obdélníku, který má všechny čtyři strany stejně dlouhé. To, že běžné OOP jazyky mají atributy a umožňují je při dědění pouze přidávat, je jejich omezení, a teprve toto omezení vede na to, že se hierarchie udělá opačně, tj. obdélník je rozšíření čtverce.
Ale fuj. Zrovna u toho čtverce a obdélníka bych se raději bez dědění obešel, než tohle. Co má takový rozšířený čtverec vracet, když se ho zeptám na stranu? Jakákoliv jen trochu příčetná volba rozbije invarianty třeba u obsahu.
Citace
Navíc pokud použijete správně zapouzdření, nebudou vám vadit ani ty atributy, protože čtverec naimplementujete tak, že nastavením jednoho rozměru změníte i druhý, a zbytek už bude fungovat jako speciální případ obdélníku.
Ještě lepší. V tomhle případě nemůžu přidávat žádné třídy dodatečně. Buď bude z rozhraní obdélníka jasné, že za ním může být schovaný i čtverec, nebo z toho bude ohavná past.
Kód: [Vybrat]
rect->setSize(s);
assert(rect->size() == s); // trololololo

Kit

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #27 kdy: 31. 08. 2015, 16:25:45 »
... také netuším ze kterého klobouku a proč do toho taháš pojmy jako je a ...

Tato dvě pomocná slovesa jsou významnou a přitom jednoduchou pomůckou při rozhodování, zda použít dědičnost či kompozici. Ještě mě nezklamala.

To je obecně špatný přístup. Dědičnost totiž není o podtypech, ale o opakovaném využití kódu. Klasický příklad, kdy děděním nevznikají podtypy, jsou tzv. binární metody.

Mýlíš se. Implementace musí být závislá na abstrakci - nikdy naopak. Opakované využití kódu z toho vyplyne zcela automaticky.

Citace
Při rozhodování, zda je něco podtyp, je lepší použít plný LSP:

V tom máš sice pravdu, ale zkus to tak vysvětlit začátečníkům. Budou na tebe civět s otevřenou hubou. Slovesa je a pochopí mnohem rychleji, přesnou definici je můžeš naučit později.

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #28 kdy: 31. 08. 2015, 16:28:19 »
No vida!

A pak bych to ještě vyšperkoval několika variacemi na téma getter a setter (ne ten pes) ...

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #29 kdy: 31. 08. 2015, 16:32:18 »
No vida!

A pak bych to ještě vyšperkoval několika variacemi na téma getter a setter (ne ten pes) ...

Ja na ten copy-paste z ucebnice OOP for Dummies cekam uz minimalne hodinu