Groovy Niko Jäntti Jesper Haapalinna Group 31
Johdanto Groovy on Apachen kehittämä Javaan perustuva dynaaminen oliopohjainen ohjelmointikieli. Kielen kehitys alkoi vuonna 2003, versio 1.0 julkaistiin 2007 ja sitä kehitetään edelleen. Groovyn ideologiana on vaihtoehtoinen tyypitys, mutta mahdollisuudella staattiseen tyypitykseen ja kääntämiseen. Suurin osa toimivasta Java-koodista toimii myös Groovyssä. Ideana onkin tarjota Java-ohjelmoijille helposti omaksuttavat tavat ja pikku hiljaa totuttaa Groovyn idioomiin. Groovy tuo Javan ominaisuuksien lisäksi muun muassa mahdollisuuden scriptaukseen ja käännösaikaiseen metaohjelmointiin. Tässä on esiteltynä lyhyesti ja pinnallisesti Groovyn tärkeimpiä piirteitä ja ominaisuuksia. Vapaaehtoinen tyypitys Groovyn vapaaehtoista tyypitystä ei tule sekoittaa joistain ohjelmointikielistä tuttuun heikkoon tyypitykseen. Vapaaehtoisessa tyypityksessä ei ole pakko eksplisiittisesti kirjoittaa muuttujan tai funktion paluuarvon tyyppiä, mutta näin voi kuitenkin halutessaan tehdä. String astring = 'foo' assert astring. touppercase () Yllä muuttuja annetaan eksplisiittisesti tyyppi String, josta tiedetään löytyvän metodi touppercase(). Näin on totuttu tekemään esimerkiksi C++-kielessä. Groovyssä voitaisiin edellinen yhtä hyvin kirjoittaa seuraavanlaiseen muotoon: def astring = 'foo' assert astring. touppercase () Staattinen ja dynaaminen tyyppitarkastus Käännettäessä Groovy suorittaa oletusarvoisesti vain minimaalisesti tyyppitarkastelua. Staattisia tyyppitarkastuksia ei ole mahdollista tehdä, sillä luokan tai olion käyttäytyminen saattaa muuttua ajon aikana. On esimerkiksi mahdollista liittää dynaamisesti ajon aikana uusi metodi olioon. Eli Groovyssä ei siis voida tietää etukäteen, miten olion tulee toimimaan. Vaikka tiedetään luokan esittely, vasta ajon aikana osataan kutsua oikeaa jäsenmuuttujaa tai metodia. On myös mahdollista kirjoittaa ohjelmakoodi perinteisellä Java -tyylillä, eli luovutaan dynaamisuudesta ja luotetaan staattiseen tyyppitarkastukseen. Kääntäjälle voidaan luokka- tai metodikohtaisesti kertoa, että halutaan käyttää staattista tyypitystä antamalla luokalle tai metodille annotaatio @groovy.lang.typechecked. Tällöin kääntäjä tekee käännöksen aikana paljon enemmän tarkasteluja ja antaa todennäköisemmin virheitä.
Syntaksi Groovyn syntaksi on hyvin samanlainen kuin suosituimmissa ohjelmointikielissä. Esimerkiksi kommentointi tapahtuu täysin samalla tavalla kuin C++:ssa ja Javassa. Mutta Groovystä löytyy mielenkiintoinen ominaisuus nimeltään quoted indentifiers. Nämä esiintyvät pisteen jälkeen pistelausekkeissa. Esimerkiksi name osuus lausekkeessa person.name voidaan lainausmerkkien avulla kirjoittaa person. name tai person. name. Mielenkiintoisempaa tässä on se, mitä tämä mahdollistaa. Lainausmerkkien sisällä voidaan muun muassa käyttää merkkejä, mitkä ovat kiellettyjä Java-kielessä, kuten alaviiva, välilyönti tai kysymysmerkki. Varsinainen käyttötarkoitus liittyy kuitenkin Groovyn merkkijonotyyppeihin. Lainausmerkkien sisälle voidaan nimittäin kirjoittaa lauseke, joka sitten evaluoidaan ohjelmaa ajettaessa. Tästä kuitenkin kerrotaan tarkemmin kohdassa Merkkijonot. Merkkijonot Groovyssa on kahdenlaisia merkkijonotyyppejä. Ensimmäinen on suoraan Javasta, java.lang.string, ja toinen on Groovyn oma GString, jota vastaavia löytyy joistain muista ohjelmointikielistä interpolated string -nimellä. Heittomerkeillä ympäröidyt merkkijonot ( tämä on lause ) ovat perinteisiä Java merkkijonoja, eikä näitä voi interpoloida. Kolmilla heittomerkeillä ympäröity merkkijono on monirivinen, esimerkiksi: tässä On Monta riviä Lainausmerkeillä ympäröidyt merkkijonot ovat myös Java -merkkijonoja, jos ne eivät sisällä interpoloitavaa lauseketta. def name = 'Guillaume' // a plain string def greeting = "Hello ${name}" assert greeting. tostring () == 'Hello Guillaume' Myös interpoloitavista merkkijonoista voi tehdä monirivisiä. Tämä tapahtuu ympäröimällä monirivinen teksti kolmilla lainausmerkeillä: def name = 'Groovy' def template = """ Dear Mr ${name}, You're the winner of the lottery! Yours sincerely, Dave """
Numerot Dynaamisuus ja vapaaehtoinen tyypitys mahdollistavat, ettei Groovy:ä kirjoitettaessa tarvitse kertoa tarkalleen numeron tyyppiä, vaan muuttuja mukautuu automaattisesti. Esimerkiksi: def a = 1 assert a instanceof Integer // Integer.MAX_VALUE def b = 2147483647 assert b instanceof Integer // Integer.MAX_VALUE + 1 def c = 2147483648 assert c instanceof Long Def -avainsanalla määriteltyyn muuttujaan voidaan myös pakottaa tietty tyyppi lisäämällä muuttujan arvon perään tyyppiä kuvaava kirjain; i = integer, bi = big integer, l = long jne. assert 42i == new Integer ( '42' ) // lowercase i more readable assert 123L == new Long ( "123" ) // uppercase L more readable Sulkeumat Groovyssä sulkeuma on avoin, anonyymi koodilohko, joka voi ottaa vastaan argumentteja, palauttaa arvon, ja joka voidaan tallentaa muuttujaan. Groovyssä sulkeuma voi viitata sekä sitä ympäröivän näkyvyysalueen muuttujiin että ympäröivän näkyvyysalueen ulkopuolella määriteltyihin vapaisiin muuttujiin. Sulkeuma määritellään noudattaen syntaksia: { [ closureparameters -> ] statements } Hakasulkeiden ympäröimä osa on vapaaehtoinen. Se sisältää luettelon sulkeuman ottamista parametreista. Jälkimmäinen osa sisältää nolla tai useamman lausekkeen. Sulkeuma on luokan groovy.lang.closure instanssi ja voidaan tallentaa muuttujaan. Sulkeumaa kutsutaan kuten tavallisia metodeja. Esimerkiksi: def printname { name -> println name } printname ("Teemu Teekkari") Groovyssä sulkeumia käytetään lambda-funktioiden sijasta ja ne ovat tärkeimpiä ominaisuuksia funktionaalisen ohjelmoinnin näkökulmasta.
Erot Javaan Groovystä on haluttu luoda mahdollisimman luontainen ohjelmointikieli Javaan tottuneille. Kuitenkin eroja löytyy, etenkin kielen dynaamisuudesta johtuen. Merkittävimpänä erona lienee kutsuttavien metodien valinta vasta ajon aikana. Tämä tarkoittaa sitä, että kun ohjelmaa ajetaan ja kutsutaan jotain metodia, oikea metodi päätellään parametrien tyyppien perusteella. Javassa tämä tapahtuu jo käännösvaiheessa. Groovyssä on tuotuna valmiiksi useimmin käytetyt paketit ja luokat, joten niitä voi käyttää ilman eksplisiittistä import-lauseketta. Lainausmerkkien ja heittomerkkien ympäröivät merkkijonot tai yksittäinen merkki on Groovy:ssä automaattisesti tyyppiä String (tai GString). Vain yhden kirjaimen sisältävä merkkijono on tyyppiä Char vain silloin, kun muuttujalle on eksplisiittisesti annettu tyypiksi char. assert 'c'. getclass ()== String char a = 'a' assert a. getclass ()== Character Toisin kuin Javassa, vertailuoperaattoreista ==-operaattori kääntyy Groovyssä metodiksi compareto(), jos vertailtavat objektit toteuttavat Comparable-rajapinnan, ja metodiksi equals() muulloin. Mikäli halutaan tarkistaa osoittavatko kaksi objektia samaan muistipaikkaan, käytetään metodia is(). Groovy ei myöskään tue Java 7:n Automatic Resource Management -lohkoja vaan sama toiminnallisuus saavutetaan käyttämällä sulkeumia, mikä yksinkertaistaa ohjelman rakennetta.