Až Vám zčerná obrazovka, přejděte na Linux!

Proč používat Linux

pondělí 14. dubna 2008

getClass() versus instanceof v equals()

Jak píše Dagi, použití if (getClass() != o.getClass()) return false; generuje chyby při použití Beanových frameworků (Hibernate, EntityBeans,...). Josh Bloch například zde doporučuje instanceof i s tím, že napsat equals() bude mnohem těžší. Otázka zní: jak ji vlastně správně napsat? Je potřeba zaručit symetričnost, takže
if (!(o instanceof this.getClass())) return false;
nic neřeší.
if (!(o instanceof this.getClass())
&& !(this instanceof o.getClass())) return false;

vypadá na první pohled lépe, ale pořád to neřeší vůbec nic.
Lze vůbec genericky prohlásit, že je možné v jakémkoli případě napsat equals() podle obecného algoritmu tak, aby odpovídala všem požadavkům na ni kladených? V případě Hibernate je bez debaty nutné použít instanceof. Co ale v případě, kdy potomek se liší od předka v přidání jednoho podstatného atributu? Pro příklad uvedu třídu popisující N rozměrný Euklidovský prostor. Jako potomka pak navrhnete třídu popisující Lobačevkého hyperbolický prostor, která pouze zavede patřičnou transformaci, která ovšem nemůže nikdy vrátit identitu na jiný prvek prostoru než bod. A v žádném případě nemůžete položit rovnítko mezi libovolnou instancí hyperbolického prostoru a euklidovského prostoru! Totéž by platilo pro systémy, které odpovídají Peanovské algebře a jejich potomky připravené o axiom indukce.
Uznávám, že se nejedná o zrovna zářné příklady. Uvedu jiný, učebnicový. V mnoha učebnicích je pro vysvětlení principů OOP použita hierarchie objektů: Bod->Obdélník->Kvádr. I zde je jasné, že nelze v žádném případě použít instanceof. Nebo dokážete pro Obdélník takovou smysluplnou symetrickou metodu equals() napsat? Čekám na vaše názory.
Mně teda jedno příšerné řešení napadlo. Použít Cimrmanova úkroku stranou a udělat z toho PNJ, tedy je-li to můj potomek, nechť to zařídí on. Ale nejsem si jist, zda jej lze použít v každém případě.

Žádné komentáře: