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

Kit

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #30 kdy: 31. 08. 2015, 16:34:37 »
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í.

Jak to čtu znovu, tak vidím jediné: Duck typing. To není zrovna nejlepší ukázkou definice dědičnosti. Možná, kdybys to nevytrhl z kontextu...


Filip Jirsák nepřihlášený

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #31 kdy: 31. 08. 2015, 16:35:36 »
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.
Třeba proto, že všechno, co platí pro obdélník, platí i pro čtverec? Když budu chtít spočítat úhlopříčku nebo obsah, proč bych to měl pro čtverec implementovat znova? Proč má uživatel mého kódu tam, kde chci na vstupu obdélník, vytvářet nový obdélník podle zadaného čtverce, místo toho, aby využil toho, že čtverec je zároveň i obdélník?

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.
Co je špatného na tom, když ten obdélník bude mít metody setStranaA() a setStranaB()? Jak se z toho pozná, že za tím může být schovaný i čtverec? Je snad něco, co můžete udělat s obdélníkem, ale ne se čtvercem? Čtverec je speciální případ obdélníku, takže všude tam, kde je očekáván obdélník, musí být možné předat i čtverec.

Kit

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #32 kdy: 31. 08. 2015, 16:40:15 »
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

V té učebnici "OOP for Dummies" používají gettery a settery? Tak už je mi jasné, proč to všichni tak propagují...

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #33 kdy: 31. 08. 2015, 16:41:16 »
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

V té učebnici "OOP for Dummies" používají gettery a settery? Tak už je mi jasné, proč to všichni tak propagují...

Skoro, Kite, skoro...

k

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #34 kdy: 31. 08. 2015, 16:43:05 »
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.

Takhle se to dělá furt. Máme FileStream a protože se nám líbí práce s ním, tak se udělá obecný abstraktní předek IOStream a pak k němu pět dalších potomků.


Radek Miček

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #35 kdy: 31. 08. 2015, 16:50:02 »
... 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.

Nerozumím, proč bych se měl mýlit. Podstatou mého tvrzení je, že použitím dědičnosti nemusí vzniknout podtyp - příkladem je třeba metoda equals, když ji otypuji equals : Self -> bool. Ve tříde Object je typ ekvivalentní equals : Object -> bool a po zdědění třídou Pes je typ ekvivalentní equals : Pes -> bool - za Self se vždy dosadí typ aktuální třídy. Je vidět, že Pes není podtyp Object, neboť argumenty metod jsou kontravariantní. Podrobněji viz článek On Binary Methods.


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í.

Jak to čtu znovu, tak vidím jediné: Duck typing. To není zrovna nejlepší ukázkou definice dědičnosti. Možná, kdybys to nevytrhl z kontextu...

Tady jde i o chování, nejen o signatury metod.

Definice je z článku Data Abstraction and Hierarchy od Barbary Liskov z roku 1988, sekce 3.3. Alternativní definice LSP je v článku A Behavioral Notion of Subtyping od B. Liskov and J. M. Winga z roku 1994 v části úvod.

Radek Miček

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #36 kdy: 31. 08. 2015, 17:03:11 »
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í.

Jak to čtu znovu, tak vidím jediné: Duck typing. To není zrovna nejlepší ukázkou definice dědičnosti. Možná, kdybys to nevytrhl z kontextu...

Jinak ještě jedna poznámka: LSP nemá s dědičností nic společného - podtřída a podtyp jsou různé věci - v některých jazycích můžete mít podtřídu aniž by to byl podtyp (viz binární metody) a také podtyp aniž by to byla podtřída.

Kit

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #37 kdy: 31. 08. 2015, 17:07:12 »
Jak to čtu znovu, tak vidím jediné: Duck typing. To není zrovna nejlepší ukázkou definice dědičnosti. Možná, kdybys to nevytrhl z kontextu...

Tady jde i o chování, nejen o signatury metod.

Právě Duck typing je definován tím chováním, signatury jsou vedlejší. Je to alternativní definice dědičnosti nikoli primární.

Je to můj syn, ale nechová se jako já  ×  není to můj syn, ale chová se jako já.

To jsou dva typy dědičnosti. Pokud modifikuji původní sloveso je na chová se, dostanu definici Duck typing dle Barbary Liskov.

JSH

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #38 kdy: 31. 08. 2015, 17:09:18 »
Co je špatného na tom, když ten obdélník bude mít metody setStranaA() a setStranaB()? Jak se z toho pozná, že za tím může být schovaný i čtverec? Je snad něco, co můžete udělat s obdélníkem, ale ne se čtvercem? Čtverec je speciální případ obdélníku, takže všude tam, kde je očekáván obdélník, musí být možné předat i čtverec.
Pozná se to z dokumentace těch metod. Může setStranaA ovlivnit i B nebo ne? Co můžu o tom obdélníku říct po jejich zavolání? Pokud to v dokumentaci nebude přímo napsané, pak bych u obdélníka očekával strany které jsou na sobě nezávislé. Ten čtverec tam nemůžu přidat dodatečně.

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #39 kdy: 31. 08. 2015, 17:13:58 »
A vidite, kolik problemu je se stavem? ;)

JSH

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #40 kdy: 31. 08. 2015, 17:20:03 »
A vidite, kolik problemu je se stavem? ;)
Souhlas. Ve chvíli kdy nemůžu měnit stav se to krásně pročistí :) V té chvíli můžu interface čtverce dědit z interfacu obdélníka a všechno se chová příčetně.

Radek Miček

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #41 kdy: 31. 08. 2015, 17:22:52 »
Jak to čtu znovu, tak vidím jediné: Duck typing. To není zrovna nejlepší ukázkou definice dědičnosti. Možná, kdybys to nevytrhl z kontextu...

Tady jde i o chování, nejen o signatury metod.

Právě Duck typing je definován tím chováním, signatury jsou vedlejší. Je to alternativní definice dědičnosti nikoli primární.

Tady ale nejsou signatury vedlejší.

Citace
To jsou dva typy dědičnosti.

Nepřijde mi, že by to mělo něco společného s dědičností. Jak jsem již říkal, můžete používat dědičnost aniž by vznikl podtyp - instance podtříd nepůjde použít tam, kde jsou očekávány instance nadtříd (kompilátor to nedovolí, protože to nedává smysl).

Radek Miček

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #42 kdy: 31. 08. 2015, 17:34:52 »
A vidite, kolik problemu je se stavem? ;)
Souhlas. Ve chvíli kdy nemůžu měnit stav se to krásně pročistí :) V té chvíli můžu interface čtverce dědit z interfacu obdélníka a všechno se chová příčetně.

Dalšími omezeními jde předejít dalším problémům. Pro C++ existují například BPravidla:

  • no virtual methods or virtual inheritance
  • no visible members or methods in any public data structure (that is, in any class declared in an .h file)
  • no mutations to public data structures
    • a strict form: no assignments or mutations whatsoever
    • a less strict form: no function may alter, directly or indirectly, any data it receives as arguments
       
       

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #43 kdy: 31. 08. 2015, 18:02:43 »
A vidite, kolik problemu je se stavem? ;)

Normálně by mělo být Square extends Rectangle a evtl. MutableRectangle extends Rectangle. Tím se oddělí "zrno od plev" (funkcionální část objektu od té měnitelné). Ovšem lepší je mít vše immutable.

JSH

Re:Omezená dědičnost (je něco lepšího než OOP?)
« Odpověď #44 kdy: 31. 08. 2015, 18:29:55 »
Dalšími omezeními jde předejít dalším problémům. Pro C++ existují například BPravidla:

  • no virtual methods or virtual inheritance
  • no visible members or methods in any public data structure (that is, in any class declared in an .h file)
  • no mutations to public data structures
    • a strict form: no assignments or mutations whatsoever
    • a less strict form: no function may alter, directly or indirectly, any data it receives as arguments
       
       
Tak tohle mi už přijde jako úlet. Zakáže polovinu C++ a pak na to ručně bez podpory překladače roubuje Haskell. C++ už je dostatečný bordel i tak. Pokud chci letadlo, tak přece nebudu šroubovat křídla na traktor. :o