Domknięcia (closures)

Domknięcie jest to mechanizm, który w Groovym jest wyjątkowo często stosowany. Ma postać bloku kodu objętego nawiasami klamrowymi. Posiada on cechy nie tylko obiektu (można go stworzyć, przesyłać do niego referencje), ale też metody(może przyjmować parametry i zwracać wartości).

Najprostszy przykład domknięcia mógłby wyglądać następująco (być może nie jest zbyt finezyjny, ale póki co sam się tego uczę)

myclosure={textToPrint->print textToPrint}
myclosure("Witaj !")


Powyższy skrypt w pierwszej linii definiuje domknięcie o nazwie myclosure, które pobiera jeden parametr o nazwie "textToPrint". Parametr ten umieszcza się po nawiasie klamrowym, a przed znakiem "->". Jego wartość jest dostępna we wnętrzu domknięcia. Powyższy przykład odwołuje się do otrzymanego parametru i wyświetla jego wartość na konsoli.

W przypadku gdy nasze domknięcie pobiera tylko jeden parametr można skorzystać z oferowanej przez Grooviego skróconej formy definicji i odwołania się do domknięcia. Wartość parametru dostępna jest we wnętrzu domknięcia po odwołaniu się do słowa kluczowego "it".

shortClosure={print it}
shortClosure("Hello Mariusz !!!")

Należy pamiętać że kod domknięcia jest wykonywany dopiero przy odwołaniu się do niego.

Możliwe jest też definiowanie domknięć przyjmujących więcej niż jeden parametr. W takim przypadku przed znakiem -> należy umieścić ich listę:

sumArgClosure={arg1,arg2-> print "SUM="+(arg1+arg2)}
sumArgClosure(5,3)

Powyższy skrypt wyświetli na ekranie napis SUM=8

Bardzo ciekawą własnością domknięć jest to, że istnieje możliwość przesyłania do nich referencji. Jako przykład niech posłuży kod klasy Calculator.

public class Calculator{
def argList=[2,3,4]

public void applyOperation(String operation,c){
print "\nWykonywana operacja to:\n***"+operation+"***"

for (elem in argList){
print "\n"+c(elem)
}
print "\n******"
}


}

def calc=new Calculator()
calc.applyOperation("Mnozeniex3"){(it*3)}
calc.applyOperation("Potegowanie"){(it*it)}

W klasie zdefiniowana jest lista argumentów (
argList=[2,3,4]) na której będą wykonywane operacje, oraz jedna metoda, która jako swój parametr przyjmuje domknięcie i tekstową nazwę operacji którą ma wykonać(chociaż znaczenie tego parametru jest mało istotne - wykorzystywane jest tylko do wyświetlenia komentarza). We wnętrzu metody zdefiniowana została pętla która przechodzi po wszystkich elementach listy argumentów, a następnie dla każdego z nich wykonuje domknięcie, przysłane do metody w parametrze :

for (elem in argList){
print "\n"+ c(elem)
}
print "\n******"
}

Wywołanie w.w. metody ma postać:

calc.applyOperation("Mnozeniex3"){(it*3)}
calc.applyOperation("Potegowanie"){(it*it)}

Za każdym razem na argumentach kalkulatora zostanie wywołana operacja zdefiniowana w domknięciu. Należy zwrócić uwagę na pewne udogodnienie, mianowicie definiowanie domknięcia przesyłanego w parametrze może wystąpić poza argumentami funkcji (chociaż notacja tradycyjna, po przecinku też jest dopuszczalna).