3.5.1. Provedení akce nad všemi prvky kolekce

Iterátor jsme při výpisu obsahu seznamu použili tak, že jsme prošli všemi jeho prvky a na každý z nich zavolali nějakou akci, konkrétně výpis metodou print(). Tato situace se v praxi vyskytuje dosti často, takže stojí za úvahu, jakým způsobem bychom takovouto operaci mohli realizovat obecně. V jazycích, které umožňují předávání funkce jako argumentu, je situace poměrně jednoduchá, např. v C++ můžeme vytvořit funkci jako

void forAll(Collection* coll, void (*operation)(void* obj));
které předáme kolekci a ukazatel na funkci, jejímž parametrem je odkaz na prvek seznamu. Tato funkce se při průchodu seznamem postupně zavolá pro všechny jeho prvky. Ovšem jak na to v Javě?

Celý vtip spočívá v tom, že operaci forAll() nepředáme ukazatel na funkci, ale referenci na objekt, jenž tuto funkci implementuje jako svou metodu. Tento objekt tedy bude implementovat následující rozhraní:

interface Command { 
   void execute(Object obj); 
}
a funkce forAll() nyní bude vypadat takto:
static void forAll(List list, Command command) { 
   Iterator it = list.iterator(); 
   while( it.hasNext() ) { 
      command.execute(it.next()); 
   } 
}

Uvedené řešení má proti variantě s ukazatelem na funkci ještě jednu výhodu. Jako parametr command můžeme předat libovolný objekt, jenž rozhraní Command implementuje. Tento objekt pak může nést další stavové informace a poskytovat další operace potřebné k provedení akce. Ukážeme si to na následujícím příkladu.

Příklad 3.9.
Vypište obsah kolekce na standardní výstup jako posloupnost očíslovaných řádků pomocí rozhraní Command.

Nejprve tedy vytvoříme třídu implementující rozhraní Command. Tato třída ponese jako data aktuální index vypisovaného prvku.

class PrintCommand implements Command { 
   int index = 0; 
 
   public void execute(Object obj) { 
      index++; 
      System.out.println(index + ": " + obj); 
   } 
}

Máme-li nyní v proměnné coll referenci na kolekci, provedeme její výpis vytvořením instance třídy PrintCommand a voláním funkce forAll():

Command cmd = new PrintCommand(); 
forAll(coll, cmd);

Java umožňuje ještě podstatně kompaktnější zápis řešení předchozího příkladu pomocí anonymní třídy:

Command cmd = new Command() { 
   int index = 0; 
   public void execute(Object obj) { 
      index++; 
      System.out.println(index + ": " + obj); 
   } 
}; 
forAll(coll, cmd); 

Podstatným rozdílem je zde to, že třídu použitou pouze na jednom místě programu nemusíme pojmenovávat, její tělo uvedeme ve složených závorkách přímo za voláním konstruktoru bázové třídy nebo rozhraní.