Zatvaranja u mjestu Groovy

1. Pregled

U ovom uvodnom vodiču istražit ćemo koncept zatvaranja u Groovyu, ključnu značajku ovog dinamičnog i moćnog JVM jezika.

Mnogi drugi jezici, uključujući Javascript i Python, podržavaju koncept zatvaranja. Međutim, karakteristike i funkcioniranje zatvarača razlikuju se od jezika do jezika.

Dotaknut ćemo se ključnih aspekata zatvaranja Groovy, pokazujući primjere kako se koriste putem.

2. Što je zatvaranje?

Zatvaranje je anonimni blok koda. U Groovyu je to instanca Zatvaranje razred. Zatvaranja mogu uzeti 0 ili više parametara i uvijek vratiti vrijednost.

Uz to, zatvaranje može pristupiti okolnim varijablama izvan svog opsega i koristiti ih - zajedno sa svojim lokalnim varijablama - tijekom izvršavanja.

Nadalje, varijabli možemo dodijeliti zatvaranje ili ga proslijediti kao parametar metodi. Stoga zatvarač pruža funkcionalnost za odgođeno izvršenje.

3. Izjava o zatvaranju

Groovy Closure sadrži parametre, strelicu -> i kôd koji treba izvršiti. Parametri nisu obavezni i, ako su navedeni, odvajaju se zarezom.

3.1. Osnovna deklaracija

def printWelcome = {println "Dobro došli u zatvaranja!" }

Evo, zatvaranje printWelcome ispisuje izjavu kad se pozove. Napišimo sada brzi primjer unarnog zatvaranja:

def print = {ime -> ime ispisa}

Evo, zatvaranje ispis uzima jedan parametar - Ime - i ispisuje kad se pozove.

Budući da definicija zatvaranja izgleda slično metodi, usporedimo ih:

def formatToLowerCase (name) {return name.toLowerCase ()} def formatToLowerCaseClosure = {name -> return name.toLowerCase ()} 

Ovdje se metoda i odgovarajuće zatvaranje ponašaju slično. Međutim, postoje suptilne razlike između zatvaranja i metode, o čemu ćemo razgovarati kasnije u odjeljku Zatvaranje vs metode.

3.2. Izvršenje

Zatvaranje možemo izvršiti na dva načina - možemo se na njega pozvati kao na bilo koju drugu metodu ili možemo koristiti poziv metoda.

Na primjer, kao uobičajena metoda:

print ("Pozdrav! Zatvaranje") formatToLowerCaseClosure ("Pozdrav! Zatvaranje") 

I izvršavanje s poziv metoda:

print.call ("Pozdrav! Zatvaranje") formatToLowerCaseClosure.call ("Pozdrav! Zatvaranje")

4. Parametri

Parametri zatvarača Groovy slični su parametrima uobičajenih metoda.

4.1. Implicitni parametar

Unarsko zatvaranje možemo definirati bez parametra jer kada parametri nisu definirani, Groovy pretpostavlja implicitni parametar pod nazivom „to":

def greet = {return "Zdravo! $ {it}"} potvrditi greet ("Alex") == "Zdravo! Alex"

4.2. Višestruki parametri

Evo zatvaranja koje uzima dva parametra i vraća rezultat njihova množenja:

def multiply = {x, y -> return x * y} potvrditi multiply (2, 4) == 8

4.3. Vrste parametara

U dosadašnjim primjerima nije naveden tip s našim parametrima. Također možemo postaviti vrstu parametara zatvaranja. Na primjer, prepišimo pomnožiti metoda za razmatranje ostalih operacija:

def izračunati = {int x, int y, Niz radnja -> def rezultat = 0 prekidač (operacija) {slučaj "DODAJ": rezultat = x + y slučaj prekida "SUB": rezultat = xy slučaj prekida "MUL": rezultat = x * y slučaj prekida "DIV": rezultat = x / y prekid} vrati rezultat} potvrditi izračunati (12, 4, "DODAJ") == 16 potvrditi izračunati (43, 8, "DIV") == 5.375

4.4. Varargovi

Možemo prijaviti promjenjivi broj argumenata u zatvaranjima, slično redovnim metodama. Na primjer:

def addAll = {int ... args -> return args.sum ()} potvrditi addAll (12, 10, 14) == 36

5. Zatvaranje kao argument

Možemo proći a Zatvaranje kao argument redovnoj Groovyjevoj metodi. To omogućuje metodi da pozove naše zatvaranje da dovrši svoj zadatak, što nam omogućuje prilagodbu njenog ponašanja.

Razmotrimo jednostavan slučaj upotrebe: izračun volumena pravilnih brojki.

U ovom je primjeru volumen definiran kao površina pomnožena s visinom. Međutim, izračunavanje površine može se razlikovati za različite oblike.

Stoga ćemo napisati volumen metoda koja zahtijeva zatvaranje areaCalculator kao argument, a mi ćemo proći implementaciju izračuna površine tijekom poziva:

def volumen (Zatvaranje areaCalculator, int ... dimenzije) {if (sizes.size () == 3) {return areaCalculator (dimenzije [0], dimenzije [1]) * dimenzije [2]} else if (dimenzije.veličina () == 2) {return areaCalculator (dimenzije [0]) * dimenzije [1]} else if (dimenzije.size () == 1) {return areaCalculator (dimenzije [0]) * dimenzije [0]}} potvrditi volumen ({l, b -> povratak l * b}, 12, 6, 10) == 720 

Pronađimo volumen konusa istom metodom:

potvrditi volumen ({radijus -> vratiti Math.PI * radijus * radijus / 3}, 5, 10) == Math.PI * 250

6. Ugniježđena zatvarača

Možemo prijaviti i pozvati se na zatvaranje unutar zatvaranja.

Na primjer, dodajmo mogućnost evidentiranja već raspravljenom izračunati zatvaranje:

def izračunati = {int x, int y, String operacija -> def log = {println "Izvođenje $ it"} def rezultat = 0 prekidač (operacija) {case "ADD": log ("Addition") rezultat = x + y slučaj prekida "SUB": zapisnik ("Oduzimanje") rezultat = xy slučaj prekida "MUL": zapisnik ("Množenje") rezultat = x * y slučaj prekida "DIV": zapisnik ("Podjela") rezultat = x / y prekid } vratiti rezultat}

7. Lijena procjena gudača

Groovy NizObično se procjenjuju i interpoliraju u vrijeme stvaranja. Na primjer:

def name = "Samwell" def welcomeMsg = "Dobrodošli! $ name" assert welcomeMsg == "Dobrodošli! Samwell"

Čak i ako izmijenimo vrijednost Ime varijabla, Dobrodošli se neće promijeniti:

name = "Tarly" potvrdi dobrodošlicuMsg! = "Dobrodošao! Tarly"

Interpolacija zatvaranja omogućuje nam lijenu procjenu Nizs, preračunato iz trenutnih vrijednosti oko njih. Na primjer:

def fullName = "Tarly Samson" def greetStr = "Zdravo! $ {-> fullName}" potvrditi greetStr == "Zdravo! Tarly Samson"

Samo ovaj put, promjena varijable utječe i na vrijednost interpoliranog niza:

fullName = "Jon Smith" potvrditi greetStr == "Zdravo! Jon Smith"

8. Zatvaranja u zbirkama

Groovy Collections koriste zatvarače u mnogim svojim API-ima. Na primjer, definirajmo popis predmeta i ispišite ih pomoću unarnog zatvarača svaki, koji ima implicitni parametar:

def list = [10, 11, 12, 13, 14, true, false, "BUNTHER"] list.each {println it} potvrditi [13, 14] == list.findAll {it instanceof Integer && it> = 13}

Često ćemo na temelju nekog kriterija možda trebati stvoriti popis s karte. Na primjer:

def map = [1:10, 2:30, 4: 5] potvrditi [10, 60, 20] == map.collect {it.key * it.value} 

9. Zatvaranja vs metode

Do sada smo vidjeli sintaksu, izvršenje i parametre zatvaranja, koji su prilično slični metodama. Usporedimo sada zatvaranje s metodama.

Za razliku od uobičajene Groovyjeve metode:

  • Možemo proći a Zatvaranje kao argument metodi
  • Unarna zatvaranja mogu koristiti implicitno to parametar
  • Možemo dodijeliti Zatvaranje na varijablu i izvršite je kasnije, bilo kao metodu ili pomoću poziv
  • Groovy određuje tip povratka zatvarača u vrijeme izvođenja
  • Možemo prijaviti i pozvati se na zatvaranje unutar zatvaranja
  • Zatvaranja uvijek vraćaju vrijednost

Stoga zatvaranja imaju prednost u odnosu na redovite metode i snažna su značajka Groovyja.

10. Zaključak

U ovom smo članku vidjeli kako stvoriti zatvarače u Groovyu i istražili kako se koriste.

Zatvarači pružaju učinkovit način ubrizgavanja funkcionalnosti u predmete i metode za odgođeno izvršenje.

Kao i uvijek, testovi koda i jedinica iz ovog članka dostupni su na GitHubu.


$config[zx-auto] not found$config[zx-overlay] not found