Neco malo jsem o nich psal v serii clanku o jazyku Lua (http://www.root.cz/clanky/funkce-v-programovacim-jazyku-lua-uzavery/#k03), ale v Jave se budou uzavery delat trosku jinak. Urcite se k tomu dostanu pri popisu novych vlastnosti v JDK 8.
Uzaver je neco jako funkce, ktera se muze odkazovat na lokalni promenne z mista, v kterem byla definovana. Tim, ze pak muzete tu funkci nekam predat, ziskavate funkcionalitu, ktera zhruba odpovida tomu provest urcity blok kodu uvnitr nejakeho uplne jineho kodu.
Dobry priklad pouziti je, ze mate nejakou datovou strukturu, jejiz implementaci neznate (a nezalezi vam na ni), a chcete nad daty z te struktury provest nejakou operaci. Pak muzete v jazyce s uzavery implementovat situaci nasledovne:
1. Implementace datove struktury zavola nad kazdym prochazenym prvkem funkci, kterou ji predate.
2. V miste, kde chcete provadet operaci nad tou datovou strukturou, tuto operaci zabalite do funkce. Protoze jazyk podporuje uzavery, neni zde zadny problem - tato funkce se muze odvolavat na lokalni promenne v miste sve definice. Tuto funkci pak predate jako argument do funkce na prochazeni te datove struktury.
Je to krasne ciste - oddelite tim technicke detaily implementace od rozhrani. Teoreticky by bylo mozne udelat rozhrani k te datove strukture, abyste ji mohl prochazet primo, ale to muze zpusobit chyby, napriklad pokud byste pozadoval, aby se po skonceni prochazeni datove struktury jeste volala nejaka funkce (napr. uvolneni zamku nebo kurzoru).
Nejsem Javista, ale mam za to, ze anonymni tridy jsou obezlicka, kterou se tvurci Javy pokusili nahradit prave silu uzaveru.
(Do jiste miry jsou uzavery a tridy dualni koncepce - pomoci uzaveru lze tridy implementovat, stejne jako lze uzavery implementovat pomoci trid. Oba postupy s sebou ale nesou samozrejme syntakticky balast. Common Lisp, ktery ma objektovy system postaveny na uzaverech, tento problem s balastem resi elegantne pomoci maker.)
Přesně tak. "Důkazem" duálnosti budiž C# a JavaScript:
V C# jsou closures implementovány pomocí tříd, které nám nageneruje kompilátor (stačí mrknout třeba Reflectorem na výslednou assembly - není to žádná magie).
V JavaScriptu se třídy "simulují" pomocí closures - resp. privátní položky se udržují v "closure of constructor function".