Tak tady bych silně nesouhlasil. Jsem C++ programátor a od operátorů očekávám, že čertoviny dělat nebudou. A taky ve všech knihovnách, které používám, žádné čertoviny nedělají.
Třeba to, že se operátor > používal pro zápis do streamu (což je blokující operace, navíc může vyhodit výjimku), tu už se v C++ nedělá?
Zrovna iostreamy jsou obecně jedna z nejhůř navržených (a taky nejstarších) částí standardní knihovny obecně. Na druhou stranu zrovna tady je z kontextu dost jasné, že tenhle operator<< opravdu nedělá nic jako bitový posun. Naproti tomu se potkávám se spoustou matematických knihoven, kde operátory dělají přesně to, co od nich intuitivně čekám.
Úplně stejně očekávám od metod, že budou dělat to, co vyplývá z jejich jména.
To já také. Jenže u spousty typů je tolik různých variant, co může dělat add() nebo equals()… Třeba máte dvě instance reprezentující v DOM následující dva XML elementy:
<f:element xmlns:f="http://example.com/namespace" />
<x:element xmlns:x="http://example.com/namespace" />
Má equals() vracet true nebo false?
No ale tohle je přesně to, na co narážím. Funkce equals nebo operátor== můžou být úplně stejně neintuitivní a matoucí. Zákaz přetěžování operátorů nevyřeší vůbec nic. Když autor knihovny pojmenuje funkci blbě, tak je vlastně úplně jedno jaké přesné ascii znaky to jsou.
Opravdu Javisti automaticky počítají s tím, že uživatelsky implementovaný kód může dělat cokoliv? Na takovéhle prasení vážně nejsem zvyklý a celkem mě překvapuje.
S tím počítají všichni dobří programátoři. Nejde o to, že by ten kód dělal něco nepředvídatelného (i když i to se stává). Ale když mám třeba kolekci, za kterou mám lokální nebo dokonce síťovou databázi, počítám s tím, že volání add() může trvat dlouho nebo může skončit třeba síťovou výjimkou. Když volám equals() na databázové entitě, ověřím si, zda se identita zjišťuje podle primárního klíče, podle hodnot nebo podle čeho. A tak dále. U operátoru ale čekám, že budou jednoduché, nebudou blokovat, nebudou vyhazovat výjimky, budou mít jednoznačný význam.
No když mám objekt, co se tváří třeba jako matice, tak od + i od add budu čekat sčítání matic. Ani v jednom případě nebudu očekávat komunikaci se vzdálenou databází. Naopak kolekce, která potichu komunikuje s nějakou vzdálenou databází je dost zákeřná, pokud se tváří jako nějaká obyčejná. Tohle zase nemá s operátory společné prakticky nic.
V tom je operátor == v Javě opravdu trochu nešťastný, protože tam je potřeba vědět, že porovnává reference. Ale zrovna C++ to má stejně, nemýlím-li se.
V C++ se operátor== obvykle přetěžuje tak, aby porovnával hodnoty. Obecně je v C++ zvykem, pokud to jenom trochu jde, aby se všechno chovalo jako vestavěné typy. Ale c++ rozlišuje samotný objekt od ukazatele na něj. Takže nemusím vůbec řešit, jak porovnávat identitu dvou objektů. Porovnávám jejich adresy resp. hodnoty dvou ukazatelů.