11.6. Domknięcia
Funkcje „pamiętają” kontekst, w jakim zostały utworzone i mogą odwoływać się do zmiennych, do których miały dostęp w momencie utworzenia. Poniższy przykład pokazuje metodę makeGreeter, która tworzy funkcję zwracającą łańcuch znaków złożony z przekazanej metodzie makeGreeter wartości uzupełnionej o liczbę powiększaną przy każdym wywołaniu funkcji.
Plik MakeGreeter.scala: def makeGreeter(greeting: String) = { var counter = 0 () => { counter = counter + 1 greeting + " " + counter } }
W poniższym poleceniu, utworzona wewnątrz metody makeGreeter funkcja anonimowa, zostaje przypisana do wartości hello.
scala> :load MakeGreeter.scala Loading MakeGreeter.scala... makeGreeter: (greeting: String)() => String scala> val hello = makeGreeter("Hello") hello: () => String = <function0>
Kolejne polecenia pokazują kilka wywołań utworzonej funkcji.
scala> hello() res0: String = Hello 1 scala> hello() res1: String = Hello 2
Można zauważyć, że łańcuch znaków zwracany przez funkcję jest za każdym razem inny. Funkcja, w momencie jej utworzenia, miała dostęp do zmiennej lokalnej counter z metody makeGreeter. Mimo że metoda makeGreeter zakończyła swoje działanie, funkcja nadal może korzystać z dostępu do tej zmiennej. Kolejne polecenie pokazuje utworzenie kolejnej funkcji za pomocą metody makeGreeter.
scala> val hi = makeGreeter("Hi") hi: () => String = <function0>
Obie utworzone funkcje mogą być wywoływane niezależnie i obie korzystają ze swojej własnej kopii zmiennej counter.
scala> hi() res2: String = Hi 1 scala> hello() res3: String = Hello 3 scala> hi() res4: String = Hi 2 scala> hello() res5: String = Hello 4