A abych si trochu hejtnul: Za celou mou relativně dlouhou kariéru jsem si u dědičnosti vystačil s pravidlem, že potomek musí být specielní verzí předka. (Všimněte si, že tam není nic o chování.) A taky si všímám, že spousta kódu, se kterým přijdu do styku se u dědičnosti tímto pravidlem neřídí. Možná je to proto, že ta dědičnost je těžká, a vývojáři ji neumí používat, ale pak je to tedy koncept na prd, a neměl by se používat vůbec.
Možná se tím neřídí proto, že se tím řídit nedá, protože to samotné pravidlo je blbost.
Příklad, kde tvou zmíněné pravidlo platí: je potřeba načítat data ze souboru, jeden řádek představuje vektor dat, ty se mají vložit do databáze. Musíš zpracovávat po dávkách, protože soubor může mít i několik gigabajtů. Každý soubor představuje jakoby jednu tabulku a tabulek existuje více, než jedna.
Budeš tedy 100% v kódu mít tuhle závislost:
TransactionRow dědí Row
AccountRow dědí Row
TransactionTable dědí Table
AccountTable dědí Table
Table agreguje Row
Platí zde pravidlo, že potomek musí být speciální verzí předka? Ano, platí. A je tenhle model správný? Jo, je.
(mimochodem tohle má na webu i Martin Fowler jako alternativu k ORM)
Pak budeš mít jinačí situaci. Chceš namodelovat situaci objektů kolem nás, třeba proto, že je v palikaci budeš chtít vykreslovat v nějaké interaktivní hře. Takže řekněme, že zrovna děláš nádoby.
Hrnek dědí Nádoba
Sklenice dědí Nádoba
Voda dědí Náplň
Hrách dědí Náplň
Nádoba agreguje Náplň
Platí zde pravidlo, že potomek musí být speciální verzí předka? Ano, platí. A je tenhle návrh ok? Ne, je úplně na piču. A přitom kde je problém? Vždyť je to v podstatě úplně to samé, jako příklad Table - Row.
Rozdíl je akorát v tom, že když se snažíme svět kolem nás napasovat do OOP, tak to vždycky dopadne špatně. Přitom zrovna na reálném světě se OOP vysvětluje na těchto hloupých případech. Třeba že Auto má Kola a Dveře. Kdybychom to chtěli potom i takhle implementovat, protože děláme třeba hru, tak je to snad ten největší antipatern.
Tak jak je možné, že v jedné situaci je jedna a ta samá věc ok a v jinačí je úplně špatně, a jakto že to jde tak dobře poznat zrovna na příkladě, modelujeme-li relativně jasně zadaný úkon v rámci PC světa a dáme úplně v principu to samé do kontrastu s reálným světem?
Je to proto, protože reálný svět je velice složitý a kdyby se chtěl namodelovat, tak by vyšlo, že všechno dědí všechno, všechno agreguje všechno a závislosti v něm jdou těžko postihnout a ikdyby šly, vychází vícejaké možnosti jak něco namodelovat, a proč? Protože OOP je úplně napiču pokud jde o modelování reálného světa, je to jen paradigma v rámci malého světa počítačů.
Přitom, soubor na disku je rovněž reálná věc.
Z toho plyne malá úprava: OOP se má používat zcela účelově a má sloužit při zpřehlednění aplikace. Neplatí žádné pravidla typu "potomek musí být speciální verzí předka", platí jenom jedno pravidlo, "musí to být účelné a dávat to to smysl v závislosti na tom, co budeme dělat" a to i v případě, kdy se chce někdo vyhnout duplicitě v kódu.
Můj názor.