A Groovy programozási nyelv

Bevezetés

1. Bevezetés


A Groovy egy a JVM-re épülő "dinamikus" nyelvek egyre bővülő csoportjából (Groovy , BeanShell , JudoScript , Pnuts , JRuby , Jacl , Jython , Rhino , stb…). A Beanshellhez hasonlóan nem egy másik szkriptnyelvre, hanem a Javára építi szintaktikáját és szemantikáját, és e mellé emeli be a dinamikus nyelvek sok képességét. A Groovy a Java platformhoz tartózó scriptnyelvként is használható. Az önmeghatározásában a Java mellett a Pythont, Rubyt és a Smalltalkot említi ősei között. A nyelv projektje 2003 augusztusában indult a Codehausnál. 2004 elején egyhangúan szavazta meg a Groovy JSR -t az SEEE végrehajtó bizottság, azóta a nyelv folyamatosan fejlődik és egyre kiforrottabbá válik. Legutolsó stabil verziója az 1.5.6-os.
Felhasználási területek
  1. Felhasználhatjuk hagyományos értelemben vett(shell) szkriptelésre.
  2. Beágyazhatjuk Java alkalmazásokba, hogy kiterjeszthetővé tegyük azt.
  3. Java alkalmazások egyes részeit írhatjuk Groovyban (pl. servletek, tesztek)
  4. Alkalmas önálló alkalmazásfejlesztésre is.
A nyelv állapota

A Groovy nyelv a JCP (Java Community Process) része. A JSR folyamat részeként három dolgot kell a fejlesztőknek elkészíteniük: A referencia implementációt (RI = Reference Implementation), egy teszt csomagot a nyelvhez (TCK = Test Compatibility Kit), a nyelv specifikációját (GLS = Groovy Language Specification). A végleges 1.0ás verziójú referencia implementációt 2007 január 2-án jelent meg. 2007 december 7-én jelent meg az 1.1-es változat, amit hamar át is neveztek 1.5-ösnek, hogy így is kifejezzék az új verzió nagy fejlődését.

A Groovy Java stílusú szintaxist használ, így azoknak, akik már ismerik a java nyelvet, a Groovy megtanulása nem okozhat gondot.
A nyelv rendelkezik a dinamikus nyelvek legtöbb képességével. A JDK osztályait sok kényelmes funkcióval egészítették ki, és a Groovy standard könyvtárában további praktikus eszközöket találunk, amik megkönnyítik a Java platformon felmerülő feladatok megoldását (pl. xml kezelés, adatbázis elérés, EJBk, string műveletek, ablakos alkalmazások, ...). A Groovy nyelv a Java nyelvből hiányolt bizonyos képességekkel is rendelkezik, úgy mint felsorolási típus, operátor túlterhelés, closure-ök (vagy névtelen függvények), dinamikus típusok. Mindezek mellett tetszőleges Java kódot is használhatunk (a Groovy tényleg a Java kiegészítése). A Groovy a JVM-re épülő nyelvek között jól teljesít sebesség szempontjából is. Az interpretált futtatás mellett a Groovy fordítható bájtkóddá, ami egyéb előnyök mellett a teljesítményt is javítja, és így más java osztályokkal is együtt használható. Jópár nyílt forrású projekt is épül a Groovyra, amit a nyelv köré épülő közösség aktívan fejleszt. Az alábbi linken a Groovyt használó projektek listáját találhatjuk. Hátránya a nyelvnek, hogy még mindig rosszul dokumentált.

2009 januárjában már letölthető volt a groovy 1.6. stabil verziója. Ebben behozták az AST Makrók néven is futó fordítási idejű metaprogramozás lehetőségét, valamint az ehhez kapcsolódó úgynevezett transzformációs annotációkat, úgy mint, @Singleton, @Lazy, @Immutable (létrejöttük után nem változó objektumok), @Delegate, és engedik a friends operátor használatát. Bevezették még a Grape-et (Groovy Advanced Packaging Engine), a hozzá tartozó grab függvénnyel és @Grab annotációval, ezzel lehetővé vált elvileg végtelen sok könyvtárra hivatkozó scriptek fejlesztése, amikben az éppen használt könyvtárak csak futási időben töltődnek le a megfelelő oldalakról (Repository), Pl: Ibiblio, Codehaus, vagy a java.net. Az 1.6.-os Groovyhoz 1370 oldalas pdf dokumentáció létezik:)

2. Főbb eltérései a Javatól

(részletesen lásd későbbi fejezetekben)

  1. A következő csomagokat nem kell importálni a forráskódban, mert alapértelmezettként importálva vannak a Groovy kódba:
    1. java.io.*
    2. java.lang.*
    3. java.math.BigDecimal
    4. java.math.BigInteger
    5. java.net.*
    6. java.util.*
    7. groovy.lang.*
    8. groovy.util.*
  2. Az == operátor: érték szerinti egyenlőséget definiál objektumokra is (ellentétben a Javával, ahol objektumok azonosságát jelentette). Tehát a Java equals()-al azonos. Objektumok azonosságára a .is() használható.
    foo.is(bar)
    Természetesen csak nem null objektumokra hívható, ezért előtte érdemes ellenőrizni az objektum null voltát:
    foo == null
  3. Az 'in' kulcsszó, nem használható változó neveként.
  4. Tömb deklarációjánál nem írható a következő:
    int[] a = {1,2,3};
    Helyette ez írható:
    int[] a = [1,2,3]
  5. A hagyományos ciklus szintaxisa mellett
    for (int i=0; i < len; i++) {...}
    használhatók a következők is:
    for (i in 0..len-1) {...}
    for (i in 0..
    len.times {...}
  6. A pontosvessző használata nem kötelező.
  7. A 'return' kulcsszó opcionális.
  8. Statikus metódusokban is használható a this kulcsszó.
  9. Az osztályok és függvényeik alapértelmezettként publikusak.
  10. A Groovy szkriptekben a Javával ellentétben nem kell minden kódot osztályokba ágyaznunk, definiálhatunk függvényeket és kiadhatunk utasításokat. A Groovy az ilyen kódot tartalmazó szkriptet is egy osztállyá fordítja, és a kódot egy run nevű metódusba rakja.

3. A Groovy használata

A nyelv telepítésének folyamata az alábbi linken olvasható.
Telepítés után négy féle képpen használhatjuk a nyelvet:

  1. interaktív módban.
  2. szkript fájlt futtathatunk.
  3. lefordíthatunk egy Groovy scriptet tartalmazó fájlt
  4. beágyazhatjuk a Groovyt egy Java alkalmazásba
Interaktív mód és szkript fájl futtatása
A telepítés után rendelkezésünkre áll egy szöveges shell
> groovysh Lets get Groovy! ================ Version: 1.0-jsr-05 JVM: 1.5.0_06-b05 Type 'exit' to terminate the shell Type 'help' for command help Type 'go' to execute the statements groovy> println "hello, world" groovy> go hello, world groovy>
Itt a kiadott parancsokat a go utasítással futtathatjuk. Van egy swing alapú konzol is, ami lényegesen kényelmesebb módja a nyelvvel való kísérletezésnek.
> GroovyConsole
Groovy console A groovy szkripteket .groovy kiterjesztésű fájlokban szokás tárolni.
helloworld.groovy println "hello, world"
> groovy helloworld.groovy hello, world >

Fordítás

Groovy szkripteket bájtkóddá fordíthatunk a groovyc ant-task segítségével a javac-hez hasonlóan. Ekkor minden Groovy osztály egy normális Java osztállyá válik, amit használhatunk a Java kódunkban, ezek az osztályok megvalósítják a GroovyObject interfészt.

Beágyazás

Groovy kódot három féleképpen ágyazhatunk Java alkalmazásokba.

Szkriptek kiértékelése

Tetszőleges szkriptet vagy kifejezést kiértékelhetünk egy GroovyShell objektum segítségével. A kiértékelt szkripttel egy Binding objektumon vagy a visszatérési értéken keresztül kommunikálhatunk. A Binding objektumban beállíthatunk változókat és a futás után visszanyerhetjük az értéküket.

Binding binding = new Binding(); binding.setVariable("foo", new Integer(2)); GroovyShell shell = new GroovyShell(binding); Object value = shell.evaluate("println 'Hello'; x = 1; return foo * 10"); assert value.equals(new Integer(20)); assert binding.getVariable("x").equals(new Integer(1));
Dinamikusan betölthetünk és futtathatunk Groovy kódot
A GroovyClassLoader osztályt használhatjuk arra, hogy Groovy osztályokat tölthessünk a java kódunkba. Tetszőleges Groovy szkript betöltésekor létrejön egy osztály, ami tartalmaz egy run metódust.
HelloWorld.groovy println "hello, world"
TestClass.java -- egy metódusán belül ClassLoader parent = getClass().getClassLoader(); GroovyClassLoader loader = new GroovyClassLoader(parent); Class groovyClass = loader.parseClass(new File("HelloWorld.groovy")); GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance(); Object[] args = {}; groovyObject.invokeMethod("run", args);

Ha Groovy osztályunk megvalósít egy interfészt, akkor kasztolhatjuk az osztály példányait az interfész típusára, és onnantól a Java kódban úgy használhatjuk, mint bármelyik Java objektumot, ami megvalósítja ezt az interfészt.

TestInterface.java public interface TestInterface { public void printIt(); }
Tester.groovy public class Tester implements TestInterface { public void printIt() { println "this is in the test class"; } }
TestClass.java -- egy metódusán belül String fileName = "Tester.groovy"; GroovyClassLoader gcl = new GroovyClassLoader(); Class clazz = gcl.parseClass(new File(fileName)); Object aScript = clazz.newInstance(); TestInterface ifc = (TestInterface) aScript; ifc.printIt();
A GroovyScriptEngine

Groovy szkriptek futtatására alkalmas még a GroovyScriptEngine. A GroovyScriptEngine-t gyökér elemek halmazával inicializálhatjuk, amik könyvtárakat, és URL-eket jelölnek. Ezután a GSE ezeken a gyökér elemeken belüli szkripteket lefordítja és képes őket futtatni. Követi a szkriptek közti függőségeket és ha valamelyik szkript megváltozik, akkor a tőle függő teljes hierarchiát újrafordítja és újratölti.

test.groovy output = "Hello, ${input}!"
TestClass.java -- egy metódusán belül String[] roots = new String[] { "/my/groovy/script/path" }; GroovyScriptEngine gse = new GroovyScriptEngine(roots); Binding binding = new Binding(); binding.setVariable("input", "world"); gse.run("test.groovy", binding); System.out.println(binding.getVariable("output"));