2009.08_Groovy na pohybel Javie, z miłością do Javy–wprowadzenie do języka_[Jezyki Programowania].pdf
(
1233 KB
)
Pobierz
441671397 UNPDF
Języki programowania
Groovy
na pohybel Javie, z miłością do Javy
–wprowadzenie do języka
Groovy to nowoczesny, dynamiczny język, w pełni integrujący się
z platformą Java, pozwalając na bezpośrednie korzystanie z mnogości
istniejących bibliotek i szkieletów.
Dowiesz się:
• Jak zacząć programowanie w języku Gro-
ovy, jaka jest jego składnia i budowa;
• Jak łączyć programy napisane w Groovim
z Javą i vice versa.
Powinieneś wiedzieć:
• Jak programować w języku Java.
Java script (ale nie JavaScript)
Kiedy powstał język Java, zachwycił on wie-
lu programistów możliwością bardzo szyb-
kiego wytwarzania aplikacji (zwłaszcza sie-
ciowych lub bazodanowych) w porówna-
niu do C++. Narzucona na poziomie kon-
cepcji języka konieczność zachowywania
pewnego porządku w kodzie, czytelność i
łatwość nauki spowodowały, że wybaczo-
no Javie ułomność związaną z jej ówczesną
wydajnością i zaczęto się nią poważnie in-
teresować. Czy jednak kodowanie w Javie
jest naprawdę takie szybkie? Wiele jej me-
chanizmów i cech (np. mocna kontrola ty-
pów) zostało stworzonych po to, by ustrzec
nas przed popełnianiem błędów, zwłaszcza
tych niewygodnych do wykrycia. Dzięki ta-
kiej koncepcji osiągnęliśmy język, którego
kod jesteśmy w stanie łatwo weryfikować
z użyciem narzędzi. Tym samym zarządza-
nie wielkimi projektami, nad którymi pra-
cują tabuny programistów, jest zwyczajnie
możliwe, a przynajmniej – prostsze. Czy
jednak składnia języka powinna brać pod
uwagę ludzką ułomność, narzucać coś, by
człowiek nie popełnił błędu? Czy nie two-
rzymy tym samym ideologii
nie myśl – pro-
gramuj
? Oczywiście celowo ubarwiam tę
kwestię, zmierzam jednak tym samym do
mniej kontrowersyjnego stwierdzenia, że
języki dynamiczne, stojące niejako w opo-
zycji do Javy, dają programiście dużo więk-
szą swobodę wyrażania myśli. Uważam, że
dobrze się dzieje, iż tego typu rozwiąza-
nia zyskują coraz bardziej na popularno-
ści. Często języki dynamicznie typizowa-
ne, o skryptowej naturze, pozwalają zako-
dować coś szybciej, wyrazić myśl w bardziej
naturalny sposób, a szablonowe fragmenty
kodu po prostu w locie wygenerować. Ry-
gor utrzymywania jakości kodu pozostaje
w tym wypadku po stronie programistów,
co może być bolączką podczas pracy zespo-
Poziom
trudności
efekcie można, w zależności od konkret-
nego problemu, stosować odpowiednie
techniki lub łączyć ideologie. Z własnego
doświadczenia wiem, że koncepcja ta jest
ze wszech miar słuszna. Groovy jest bar-
dzo ciekawym pomysłem na rozszerzenie
wiedzy o językach dynamicznych i funk-
cyjnych (zakładam, że większość Czytel-
ników tego artykułu ma przede wszyst-
kim doświadczenie obiektowe, z językami
mocno typowanymi). Groovy powstał ja-
ko konglomerat różnych pomysłów, które
na przestrzeni czasów pojawiły się w war-
tościowych językach programowania. Mo-
że przez to połączenie jest czasem nieco
przesadzony
, jednak jego poznanie może
znacząco ułatwić podróże w kierunku ję-
zyków odległych Javie. Siłą Grooviego (dla
programistów Javy) jest to, że ucząc się no-
wej koncepcji, wciąż pozostajemy w świe-
cie dobrze nam znanym i używamy tych
samych bibliotek. Nie będzie to zatem na-
uka od zera.
Artykuł dedykowany jest dla osób, któ-
re o Groovim w ogóle nic nie wiedzą al-
bo jedynie coś, gdzieś, kiedyś słyszeli. Je-
śli masz już, drogi Czytelniku, pewne do-
świadczenie z Groovim i interesujesz się
tworzeniem aplikacji internetowych, za-
chęcam do przeczytania artykułu Ma-
riusza Roga pt.
Grails, Groovy i ruszto-
wania
na temat szkieletu Grails. Arty-
kuł opublikowany jest w niniejszym wy-
daniu SDJ.
cza tych, którzy przesiąkli pew-
nymi nawykami, nauka nowego
języka programowania (lub choćby okaza-
nie mu zainteresowania) jest porównywal-
na do zdrady partnera. Jest to niestety po-
dejście dość radykalne i leniwe, bowiem z
każdego wartościowego języka (a postaram
się udowodnić, że Groovy do takich należy)
można nauczyć się wiele nowego, nawet je-
śli finalnie pozostanie się przy swoim ulu-
bionym rozwiązaniu. Koncepcja ta została
doskonale opisana w artykule Petera Norvi-
ga pt.
Poznaj sztukę programowania w dzie-
sięć lat
(dostępnym na stronie internetowej
http://norvig.com/21-days.html
). Autor suge-
ruje, by poznać kilka różnych koncepcyjnie
języków (przynajmniej jeden funkcjonal-
ny, jeden obiektowy i równoległy) do tego
stopnia, by zacząć umieć myśleć w tych ję-
zykach (a nie tylko poznać ich składnię, jed-
nak programować z użyciem dotychczaso-
wych nawyków). Rezultatem takiego do-
świadczenia powinno być szersze spojrze-
nie na programowanie jako sztukę tworze-
nia kodu, z pominięciem ograniczeń narzu-
canych przez pojedyncze rozwiązanie. W
26
08/2009
D
la wielu programistów, zwłasz-
Groovy
łowej. Można by zatem rzec, iż skrypty nie
są dla idiotów. Chaos, jaki można stworzyć
skryptem choćby w średniej wielkości pro-
jekcie, może pozostać nie do ogarnięcia na-
wet dla programistycznego guru. Czy to
jednak powinno bronić nas przed używa-
niem mniej schematycznych (od Javy) ję-
zyków programowania? Jedynie o Lispie i
SQLu mówi się, iż programowanie w tych
językach składa się przede wszystkim z my-
ślenia, a zapisywanie kodu to jedynie trzy-
dzieści procent czasu. Myślenie jednak nie
boli, natomiast patrzenie na kod, który z ła-
twością można by wygenerować lub stwo-
rzyć z użyciem techniki kopiuj-wklej, mo-
że co wrażliwszych programistów doprowa-
dzić do zapalenia spojówek.
Wystarczy już krytyki na temat Javy – ję-
zyk ten ma wiele dobrych cech. Przez la-
ta Java dorobiła się ogromnej ilości bi-
bliotek, szkieletów, narzędzi programi-
stycznych – stabilnych i pisanych na pro-
fesjonalnym poziomie, często przez uzna-
ne instytucje. Stworzył się standard. Java
jest jedną z najczęściej rozważanych alter-
natyw przy tworzeniu wielkich aplikacji
korporacyjnych, integrujących różne śro-
dowiska, trzon dla wielu rozwiązań webo-
wych. Żaden z języków wyższego poziomu
nie otrzymał tak profesjonalnego wsparcia
i pewnie żaden nie wygenerował twórcom
programów takich zysków, jak Java. Przy-
kładowo Python, który jest językiem prze-
estetycznym i wygodnym w pisaniu, bory-
ka się z nadmiarem niejednorodnych i nie-
kompletnych rozwiązań i bibliotek, często
pisanych amatorsko, na kolanie. Nawet je-
śli na dobrym poziomie, to bez niezbędne-
go wsparcia, zapewniającego profesjonalny
rozwój rozwiązań. Kolejny język nadający
się do szybkiego pisania aplikacji i bardzo
naturalnego sposobu wyrażania myśli – Ja-
vaScript – praktycznie nie istnieje poza śro-
dowiskiem przeglądarek. Powstałe rozwią-
zania są wykorzystywane co najwyżej przez
pasjonatów niż twórców poważnych aplika-
cji, a sam język, ze względu na marginal-
ną wiedzę na jego temat pośród większo-
ści programistów, często nie cieszy się do-
brą opinią.
W takiej sytuacji niesamowitym kompro-
misem byłby język, który pozwoliłby na sko-
rzystanie z ogromu rozwiązań powstałych
dla języka Java, jednak z drugiej strony miał-
by naturę bardziej dynamiczną, pozostawia-
jącą programiście dużą dowolność. Taki ję-
zyk doskonale nadawałby się do pisania mi-
kroprogramów lub małych narzędzi, jak i
wielkich aplikacji. Taki język powinien, w
razie konieczności, pozwalać na implemen-
tację części funkcjonalności bezpośrednio w
języku Java lub w aplikacjach Java być wyko-
rzystywanym do implementacji tych frag-
mentów, które łatwiej jest opisać skrypto-
wo. Taki język.... to Groovy. Gdyby nazwa
JavaScript nie została już (zupełnie nieade-
kwatnie) zarezerwowana, Groovy byłby naj-
pewniej określany w ten właśnie sposób.
Choć może to stwierdzenie nieco na wyrost
– Groovy jest w końcu językiem kompilowa-
nym, zachowuje jednak wiele cech języków
skryptowych.
namiczną, jak i silną typizacją. Mimo że jest
językiem kompilowanym, umożliwia znaczą-
ce modyfikowanie prototypów klas oraz dy-
namiczne uruchamianie kodu. Do podsta-
wowych różnic w stosunku do języka Java na-
leżą: domknięcia, możliwość przeładowywa-
nia operatorów, wyrażenia regularne wbudo-
wane w składnię języka, koncepcja właściwo-
ści klas (ang.
properties
) oraz możliwość ewa-
luacji wyrażeń.
Trochę faktów
Oficjalny manual Grooviego we wstępie wita
na pokładzie nowego języka, każe zapiąć pasy
i wznieść się na wyżyny programowana. Lot-
nicze skojarzenie ma zapewne źródło w histo-
rii (a może – legendzie) powstania języka. Je-
go twórca – James Strachan – wpadł na pier-
wotną ideę Grooviego, przeglądając na lotni-
sku, w oczekiwaniu na samolot, artykuły na
temat Pythona. Jako zagorzały programista
Javy, nie miał wielkiego doświadczenia z języ-
kami bardziej dynamicznymi i doznał praw-
dziwego olśnienia, widząc, jak wielkimi skró-
tami myślowymi można posługiwać się, pro-
gramując w Pythonie. Zaczął rozwijać kon-
cepcję języka, czerpiąc z istniejących rozwią-
zań, starając się jednak zachować pełną zgod-
ność z Javą. Podstawową ideą było utworzenie
języka, który bez żadnych dodatkowych me-
chanizmów będzie mógł korzystać z ogromu
bibliotek Javy, jak również, który z poziomu
języka Java będzie rozpoznawany jako spójny
fragment programu. Minęło prawie sześć lat
od tego czasu. Język Groovy, dzięki zapałowi
twórcy i jemu podobnych pasjonatów – po-
wstał i znalazł swoją pozycję. Ma coraz więk-
sze grono zwolenników. Z drugiej strony, po
sześciu latach od powstania, wielu programi-
stów Javy nie zna nawet podstawowych kon-
cepcji Grooviego, którego używanie nie musi
być wcale
zdradą
Javy, a jedynie jej praktycz-
nym uzupełnieniem. Właśnie im dedykowa-
ny jest ten artykuł.
Groovy jako koncepcja języka powstał w
2003 roku, jednak na pierwszą oficjalną i
stabilną implementację (wersja 1.0) trzeba
było czekać aż do 2007 roku. Jeszcze w tym
samym roku została wydana znacznie po-
prawiona wersja 1.1, która dla podkreślenia
zmian została szybko przemianowana na 1.5.
W chwili pisania artykułu dostępna była wer-
sja 1.6.3 z maja 2009 roku. Ostatnie dwa la-
ta to okres silnego zainteresowania językiem
oraz rozwoju dedykowanych szkieletów i na-
rzędzi. Aktualnie trwają prace nad jego stan-
daryzacją zgodnie z
Java Community Process
(JSR241).
Język Groovy definiuje się jako dynamicz-
ny (często także pada określenie – skrypto-
wy) język obiektowy dedykowany platfor-
mie Java. Najczęściej porównuje się go do ta-
kich języków jak Python, Ruby, Perl i Small-
talk. Groovy charakteryzuje się zarówno dy-
Web is dead
Web is dead
, czyli nieco bardziej cyberpun-
kowy
Hello world
. W końcu i tak chodzi tyl-
ko o wygenerowanie jakiegokolwiek tekstu na
ekranie. A ponieważ jest to offline'owy ekran
konsoli systemowej, tekst będzie na miejscu.
Niniejszym ogłaszam najkrótszy w historii
SDJ rozdział poświęcony temu zagadnieniu.
Oto rozwiązanie
groovy -e "print 'Web is dead'"
Ktoś chciał coś powiedzieć o statycznej me-
todzie
main
jakiejś tam klasy, przyjmującej w
parametrze tablicę? Hmm...
Środowisko języka Groovy
Przedstawiony powyżej pierwszy program
niewiele nam jeszcze mówi o samym języ-
ku i możliwości uruchamiania jego progra-
mów. Zajmijmy się najpierw tym drugiem.
Groovy pozwala kompilować kod do plików
.
class
, pozostając nieodróżnialnym od Ja-
vy dla maszyny wirtualnej tego języka. Mo-
że też, tak jak zrobiliśmy to w przypadku
pierwszej aplikacji, uruchomić kod bezpo-
średnio z wiersza poleceń – dzięki przełącz-
nikowi
-e
polecenia
groovy
. Kolejną, bardzo
wygodną w trakcie nauki opcją jest konsola
(uruchamiana poleceniem
groovyConsole
),
w której szybko możemy pisać małe frag-
menty kodu i obserwować ich działanie.
Rysunek 1.
Konsola języka Groovy pozwala
w łatwy sposób testować małe programy, bez
konieczności jawnej kompilacji
www.sdjournal.org
27
Języki programowania
Wygląd konsoli języka zaprezentowano na
Rysunku 1.
Pracując z konsolą, bądź uruchamiając
programy z użyciem narzędzia
groovy
, mo-
żemy odnieść wrażenie, że Groovy jest języ-
kiem interpretowanym. Gdyby tak było, je-
go integracja z Javą nie byłaby już taka pro-
sta. W rzeczywistości Groovy zawsze tworzy
pliki
class
, choć czasem może to być ukryte
dla programisty – kompilator może umiesz-
czać klasy w plikach tymczasowych lub bez-
pośrednio w pamięci. Zazwyczaj jednak bę-
dziemy jawnie odwoływać się do standar-
dowych plików .
class
. By je otrzymać – po-
trzebujemy kompilatora, a więc narzędzia
groovyc
. Polecenie
kie niezbędne pliki są osadzone w jednym
pliku
jar
, zajmującym ponad 4MB. Uru-
chomienie skompilowanej klasy Groovy
(
Test.class
) będzie zatem wyglądało nastę-
pująco:
nej typizacji obiektów. Silna typizacja, będą-
ca cechą języka Java, niejednokrotnie wymu-
sza konieczność częstego jawnego rzutowa-
nia. Groovy rozwiązuje ten problem w sytu-
acjach, w których nie jest to potrzebne, w in-
nych pozwala natomiast na zachowanie kon-
troli typów. Oto przykład:
java -cp groovy-all-1.6.0.jar; Test
Podstawowa składnia
Wiemy już, jak uruchamiać programy języka
Groovy, skupmy się zatem na prostych przy-
kładach mających na celu zobrazowanie cech
języka. Zachęcam do uruchamiania ich z po-
ziomu konsoli
groovyConsole
. Zakładam, że
Czytelnicy tego artykułu znają przynajmniej
na podstawowym poziomie Javę, postaram
się więc położyć szczególny nacisk na wskaza-
nie różnic między tym językiem a Groovym.
Przedstawiony wcześniej pierwszy, jed-
nowersowy przykład (
Web is dead
) wska-
zał już na kilka istotnych różnic (i skró-
tów) przyjętych przez język Groovy. Funk-
cja
print
została użyta bez nawiasów, za-
brakło też końcowego średnika. Oba te ele-
menty nie są wymagane, o ile jasno z kon-
tekstu można zrozumieć intencje wyko-
nania kodu. Średnik zwykle przyda się
w przypadku umieszczenia w jednej linii
programu kilku niezależnych wywołań.
Pomijanie nawiasów w wykonaniu funk-
cji zwykle może zagmatwać czytelność,
choć zwyczajowo opuszcza się je dla funk-
cji
print
. Ponadto będzie to bardzo przy-
datne przy pracy z domknięciami, o czym
w dalszej części artykułu.
Podstawową różnicą między Javą a Gro-
ovim jest możliwość używania dynamicz-
def a=1
Integer b = 1
a = "test"
b = "test" //błąd
W języku Groovy nie musimy tworzyć kla-
sy, by napisać prosty kod (kompilator utwo-
rzy ją w takiej sytuacji domyślnie). Możemy
zatem bezpośrednio zająć się pisaniem kodu
lub zamiast klas korzystać wyłącznie z funk-
cji. Deklaruje się je następująco:
groovyc *.groovy
utworzy pliki
.class
dla zadanego katalogu.
Od tego momentu będziemy mogli skorzy-
stać z nich w jakimś projekcie języka Java
lub zwyczajnie uruchomić. Ciekawą opcją
kompilatora
groovyc
jest możliwość użycia
narzędzia
javac
celem jednoczesnego skom-
pilowania plików
.groovy
i
.java
i rozwiąza-
nia zależności tkwiących między tymi plika-
mi. Służy do tego przełącznik
-j
:
def poleKola(promien) {
Math.PI * promien**2
}
Powyższy kod ma kilka ciekawych cech. Po
pierwsze – nie określamy typu zwracane-
go, wiemy już zatem, że będzie on miał dy-
namiczny charakter. Po drugie – odwołu-
jemy się tu do właściwości
PI
klasy
Math
–
tej samej, której używa język Java. Po trze-
cie – użyliśmy nieobecnego w Javie opera-
tora potęgowania (
**
). Finalnie zaś – zwra-
camy wartość funkcji bez użycia słowa klu-
czowego
return
. Użycie go jest opcjonal-
ne – w przypadku jego pominięcia zostanie
wzięta pod uwagę wartość ostatniej linii ko-
du funkcji.
groovyc -j Test.groovy Main.java
Skompilowane pliki
.groovy
będziemy
uruchamiać tak jak każdy program Ja-
vy. Musimy tylko pamiętać o dodaniu do
ścieżki niezbędnych bibliotek. Ponieważ
ich ilość jest niemała, możemy skorzy-
stać z dystrybucji języka, w której wszyst-
Niestandardowe operatory
Poniżej znajduje się opis operatorów języka Groovy, które nie mają swoich bezpośrednich odpowiedników w Javie lub które w Javie występu-
ją, lecz zyskały tutaj dodatkowe znaczenie.
•
a ** b
– potęgowanie; podnosi
a
do potęgi
b
.
•
*lista
– konwertuje listę do ciągu oddzielnych parametrów; w praktyce pozwala na przekazanie funkcjom parametrów w posta-
ci listy, np.
"text".substring(*[1,2])
; operator może też być użyteczny przy dodawaniu nowych elementów do listy lub mapy, np.:
[1,2,3,*[4,5,6]]
utworzy sześcioelementową, płaską listę.
•
a[b]
– udostępnia obiekt pod wskazanym indeksem, działa zarówno z tablicami, jak również listami i mapami; umożliwia odczyt i zapis da-
nych.
•
a << b
– klasyczne przesunięcie bitowe w lewo, jednak dla niektórych typów posiada przeładowane znaczenie typu
dodaj
,
uzupełnij o ele-
ment.
W tej formie operuje na obiektach
StringBuffer
, klasach typu
Writer
, plikach, gniazdach, listach i metaobiektach.
•
<=>
– komparator, ze względu na wygląd nazywany statkiem kosmicznym (ang
spaceship
); służy do porównywania wartości obiektów.
•
a as typ
– tworzy wymuszenie rzutowania bądź alias dla jakiegoś typu. W tym pierwszym przypadku możemy użyć operatora np. do za-
inicjalizowania obiektu z użyciem listy:
def obj = [1,2,3] as MyClass
. Aliasowanie pozwala natomiast na uniknięcie konliktów nazw,
poprzez ich import pod nową nazwą, np.
import java.sql.Date as SQLDate
•
a .@ b
– bezpośredni dostęp (z pominięciem metody
get
) do składnika
b
obiektu
a
.
•
a .& b
– zwraca referencję do metody
b
obiektu
a
w postaci domknięcia; kontekst obiektu zostaje zachowany (odwołania z użyciem
this
);
operator może mieć zastosowanie np. przy przekazywaniu metody w postaci parametru do funkcji oczekujących na wejściu domknięcia
(np.
lista.each(obiekt.&metoda)
)
•
a .. b
– operator zakresu, np
(1..20)
; istnieje możliwość stworzenia przedziału prawostronnie otwartego, np.
(100..<105)
.
•
a *. b
– odnosi się do właściwości lub metody
b
każdego obiektu zawartego w kolekcji
a
; przykładowo kod
["a","b","c"]*.toUpperCase
()
zwróci w rezultacie listę
["A","B","C"]
.
•
a ?. b
– opcjonalny dostęp do elementu;
b
zostanie użyte, tylko jeśli
a
nie ma wartości
null
; pozwala uniknąć pisania dodatkowych wa-
runków i znacząco zmniejsza ryzyko wystąpienia w kodzie wyjątków typu
Null pointer exception
.
•
==~
– operator dopasowania w wyrażeniach regularnych.
•
=~
– operator przeszukiwania w wyrażeniach regularnych.
28
08/2009
Groovy
GString
Operacje na łańcuchach znaków są często
niezwykle istotnym elementem programów,
a przy niewygodnych mechanizmach potra-
fią znacząco utrudnić programistom życie.
Groovy wychodzi tu na pomoc z rozbudo-
waną koncepcją obsługi tekstów i wbudo-
wanym w język wsparciem dla wyrażeń re-
gularnych. Oprócz implementacji klasycz-
nych obiektów
java.lang.String
, znaj-
dziemy tu rozszerzenie w postaci klasy
groovy.lang.GString
, która umożliwia do-
stęp do zmiennych z poziomu łańcuchów
znaków, jak ma to miejsce w wielu językach
skryptowych:
dykowanych operatorów, celem odróżnienia
od zwykłych łańcuchów znaków:
Pierwszą dostrzegalną różnicą jest uży-
cie dynamicznego typu (
def
). Dzięki te-
mu polu
author
będziemy mogli, w za-
leżności od potrzeby, przypisać np. prosty
napis, obiekt klasy
Person
lub listę tych
obiektów.
Nigdzie w przykładzie nie umieściliśmy
operatora zakresu – w przypadku Groovie-
go nie oznacza to jednak, że składowe klasy
przyjmą domyślnie zakres pakietu. Dla me-
tod domyślnym zakresem jest
public
, nato-
miast dla pól –
private
.
Ponieważ jak dotąd nie zdefiniowaliśmy w
klasie żadnego konstruktora, mamy, podob-
nie jak w Javie, do dyspozycji bezparametro-
wy konstruktor domyślny. Ponadto standar-
dowo Groovy udostępnia jeszcze jeden kon-
struktor, dzięki któremu możemy w trakcie
inicjalizacji obiektu ustawić wartości pól za
pomocą mapy:
def pattern = ~/a(.*)d/
Możemy teraz spróbować porównać dowol-
ny napis ze zdefiniowanym wzorcem – słu-
ży do tego operator
==~
:
if( 'abc' ==~ pattern ) { … }
Chcąc otrzymać wszystkie odpowiadające
wzorcowi dopasowania, należy skorzystać
z kolejnego operatora, który w rezultacie
zwróci listę wyników:
public class Person {
def irstname, lastname
String toString() {
"$irstname $lastname"
}}
def matches = 'abcd' =~ pattern
Dla naszego przykładu będzie to dwuele-
mentowa lista
['abcd', 'bc']
Jak widzimy na tym prostym przykładzie,
łatwo możemy pozbyć się niewygodnej kon-
katenacji łańcuchów. Może mieć to zastoso-
wanie w wielu sytuacjach, np. w servletach,
przy tworzeniu zapytań SQL itp.
Rozróżnienie między klasycznym
Stringiem
a
GStringiem
odbywa się po użytych znakach
cytowania. Pojedynczy cudzysłów tworzy
obiekty klasy
java.lang.String
i w tej sy-
tuacji nie ma możliwości interpolacji zmien-
nych. Podwójne cudzysłowy umożliwiają sko-
rzystanie z zalet obiektów
GString
.
Groovy wprowadza jeszcze jedno bardzo
ciekawe udogodnienie, umożliwiające ope-
rowanie na długich, wielowersowych łańcu-
chach znaków. Służą do tego pojedyncze lub
podwójne cudzysłowie (w zależności, czy
chcemy rozwijać wartości wyrażeń, czy nie),
użyte trzykrotnie:
Tworzenie klas – podstawy
Definiowanie klas w języku Groovy w wersji
podstawowej przypomina mocno Javę. Na wyż-
szym poziomie szczegółowości pojawia się tu
jednak wiele elementów rozbudowujących ba-
zową składnię. W niniejszym opisie stworzymy,
krok po kroku, przykładową klasę, skupiając się
na istotnych cechach języka. Niech będzie to
klasa opisująca języki programowania. Zacznij-
my od kilku podstawowych pól:
def pl = new ProgrammingLanguage(name:
"Perl", author: "Larry Wall")
Konstruktory te będą dostępne dopóty nie
zdefiniujemy własnych. Implementacja kon-
struktora wygląda tak samo jak w Javie:
ProgrammingLanguage(String name) {
this.name = name
}
public class ProgrammingLanguage {
String name
def author
String helloWorldCode
}
Gdybyśmy konstruowali naszą przykłado-
wą klasę w Javie, z pewnością uzupełni-
libyśmy ją o metody
get
i
set
dla poszcze-
gólnych pól, zwłaszcza że są one prywat-
ne i nie powinniśmy mieć do nich bezpo-
Listing 1.
Przykład użycia budowniczego SwingBuilder do szybkiego tworzenia interfejsu użytkownika
import
groovy.swing.SwingBuilder
def txt = """Dzisiaj jest ${new Date()}.
Test długiego napisu w języku Groovy"""
swing
=
new
SwingBuilder
()
frame
=
swing
.
frame
(
title:
'
Groovy
Builder
') {
menuBar
{
menu
('
Help
') {
menuItem
'
Help
'
menuItem
'
About
'
}
}
panel
{
boxLayout
(
axis:
javax
.
swing
.
BoxLayout
.
Y_AXIS
)
label
'
Hello
World
'
button
(
text:
'
Exit
',
actionPerformed:
{
event
->
System
.
exit
(
0
)}
)
}
}
Kolejnym rozszerzeniem jest możliwość
używania operatorów
<<
i
<<=
do konkate-
nacji stringów. Jest to dość czytelne odróż-
nienie operacji łączenia napisów od doda-
wania numerycznego (choć operatory
+
i
+=
również funkcjonują prawidłowo na tek-
stach). Najbardziej przydatna jest tu możli-
wość użycia operatora
<<
na obiektach kla-
sy
StingBuffer
zamiast metody
append
.
Pisząc o operacjach na tekstach, nie sposób
nie wspomnieć o wyrażeniach regularnych,
które w Groovim mają pełne wsparcie bez-
pośrednio z poziomu języka. Przyjrzyjmy się
zupełnym podstawom, skupiając się przede
wszystkim na składni (wyrażenie regularne
to osobny temat, wykraczający daleko poza
zakres tego artykułu). Definicja wzorca wy-
rażenia regularnego odbywa się z użyciem de-
frame
.
pack
()
frame
.
show
()
www.sdjournal.org
29
Języki programowania
średniego dostępu. Zróbmy eksperyment
w Groovim:
należy to zrobić jawnie, tak jak pokazano to
na przykładzie dla właściwości
author
.
Gdybyśmy w ogóle nie chcieli mieć metod
dla jakiegoś pola, wystarczy zadeklarować je
jako
private
. Groovy generuje metody tylko
dla właściwości o niezdefiniowanym zakre-
sie. Nic też nie stoi na przeszkodzie, by nadpi-
sać metodę pobierającą wartość lub ją zwraca-
jącą. Będziemy musieli to zrobić dla sytuacji,
w których metoda będzie miała za zadanie
wykonać dodatkowe czynności lub kiedy bę-
dziemy chcieli ograniczyć jej widoczność (np.
do
protected
). Jeśli właściwość klasy zosta-
nie zadeklarowana jako
final
, zostanie natu-
ralnie utworzona jedynie metoda
get
.
Wiemy już, jak definiować klasy, ich po-
la, metody i specjalne pola – właściwości.
Podobnie jak w przypadku języka Java, kla-
sy mogą dziedziczyć po sobie z użyciem kon-
strukcji
extends NazwaNadklasy
. Natomiast
mamy tu ograniczenia w postaci braku moż-
liwości używania klas wewnętrznych (mo-
żemy zamiast nich skorzystać z domknięć).
Również interfejsy wymagają specjalnego
traktowania. Zostało to opisane w dalszej czę-
ści artykułu.
dynamicznej typizacji, zatem obiekty umiesz-
czane na liście mogą być dowolnego typu.
W sposób zbliżony do list tworzyć bę-
dziemy mapy (a konkretnie obiekty klasy
LinkedHashMap
):
def sch = new ProgrammingLanguage("Scheme")
sch.author = ["Guy L. Steele", "Gerald Jay
Sussman"]
Zadziwiająco – powyższy kod skompiluje
się. Co więcej, również taki kod nie zwróci
żadnego błędu:
def colors = [ white: "#FFFFFF", red:
"#FF0000" ];
Korzystając z powyżej notacji, łatwo możemy
utworzyć pustą listę (
[]
) oraz pustą mapę (
[:]
).
Definicja tablicy (jest to raczej rzadko uży-
wana w Groovim struktura danych) wymaga
określenia konkretnego typu tablicowego (ce-
lem odróżnienia od listy), np.
sch.setHelloWorldCode('(display "Hello
World!")')
Myślę, że osoby znające np. podstawy języ-
ka C# mogą już wiedzieć, co się stało. Gro-
ovy chroni nas przed koniecznością pisania
oczywistego kodu, którego apogeum stano-
wią wszechobecne metody
get
i
set
. Zaledwie
w znikomej ilości przypadków metody te ro-
bią cokolwiek ponad ustawianie wartości
pól prywatnych. Łatwo można je zatem ge-
nerować, co jest cechą wielu środowisk pro-
gramistycznych języka Java. W przypadku
Grooviego – zrobi to za nas sam język! Upo-
rządkujmy wiedzę – deklarując pole klasy
bez podania zakresu widoczności, tworzy-
my de facto właściwość (ang.
property
), któ-
ra jest prywatna, automatycznie jednak zo-
staną dla niej wygenerowane publiczne me-
tody
get
i
set
. Możemy odwoływać się do nich
przez nazwę, jednak również bezpośrednie
odwołanie do pola klasy uruchomi w rzeczy-
wistości metodę. Jedynie w obrębie samej
klasy będziemy korzystać bezpośrednio ze
zmiennych, a nie metod. Stwórzmy na przy-
kład metodę
toString
:
int[] numbers = [1,2,3]
Zwróćmy uwagę, że elementy tablicy są za-
inicjalizowane tak jak lista – z użyciem kwa-
dratowych nawiasów. W Javie użylibyśmy tu
nawiasów klamrowych.
Specyficznym typem, który nie posiada
swojego bezpośredniego odpowiednika w Ja-
vie, jest zakres (ang.
range
) definiujący ciąg
kolejnych elementów:
Tablice, listy, mapy i zakresy
W Groovim znacznie częściej niż w Javie bę-
dziemy operować na tablicach i mapach dzię-
ki możliwości ich szybkiego, dynamicznego
tworzenia. Tego typu konstrukcje są zresztą
domeną wielu języków dynamicznych – w
Lispie praktycznie wszystko jest listą, w Ja-
vaScripcie każdy obiekt będzie mapą (tabli-
cą asocjacyjną) itp.
Groovy umożliwia tworzenie kolekcji w
sposób identyczny jak w Javie, jednak częściej
korzystać będziemy ze znacznie szybszej no-
tacji operatorowej:
def zakr = 100..200
Zakresy mogą mieć wiele praktycznych za-
stosowań, jak np. iterowanie pętli po kolej-
nych elementach:
for( i in 1..10 ) { ... }
lub wypełnianie list kolejnymi wartościami
(przykład tworzy listę elementów od 1 do 5
oraz od 20 do 25, czyli łączy ze sobą dwa za-
kresy):
String toString() {
"$name, created by ${getAuthor()}"
}
list = [*(1..5), *(20..25)]
def lista = [1,2,3,"tekst", new Object()]
Ponieważ jest to metoda tej samej klasy, nie
mamy potrzeby korzystania z metody
get
. W
razie konieczności możemy jej użyć, jednak
Zapis powyżej tworzy kolekcję typu
ArrayList
i wypełnia ją pięcioma obiektami. Używamy tu
Operatory i ich przeładowywanie
Język Groovy wprowadza kilka ciekawych
operatorów. Część z nich opiszemy bar-
Iterowanie z Groovim
Groovy rozszerza klasę
java.lang.Object
o dodatkowe metody ułatwiające iterowanie po elementach z użyciem domknięć, co praktycznie
zwalnia programistę z konieczności używania pętli. Metody te można stosować dla wszelkiego rodzaju kolekcji, enumeracji, zakresów i łańcu-
chów znaków. Poniżej przedstawiono ich listę wraz z przykładami użycia. Każda z opisanych tu metod przyjmuje w parametrze domknięcie.
•
any
– zwraca wartość
true
, jeśli domknięcie zwróci taką wartość dla przynajmniej jednego z elementów. Przykładowo, kod
[null, null,
1, null].any{ it != null }
sprawdzi, czy lista zawiera niepuste elementy.
•
collect
– zwraca listę wartość zwróconych przez domknięcie dla każdego z elementów wejściowych. Przykładowo,
"text".collect{
it.charAt(0) }
zwróci listę znaków składających się na napis wejściowy.
•
each
– uruchamia przekazane domknięcie dla każdego elementu listy wejściowej. W rezultacie zwraca listę wejściową.
•
eachWithIndex
– podobnie jak
each
, ale domknięcie przyjmuje jeszcze drugi parametr, będący indeksem obiektu w kolekcji.
•
every
– działa podobnie jak
any
, jednak zwraca wartość
true
,tylko jeśli dla wszystkich elementów wejściowych domknięcie zwróciło war-
tość
true
.
•
ind
– przekaże w rezultacie pierwszy element z listy, dla którego domknięcie zwróci wartość
true
.
•
indAll
– jak wyżej, ale wygeneruje listę wszystkich wartości zgodnych z domknięciem wejściowym. Przykładowo, kod
(1..50).indAll{
it % 2 == 0 }
zwróci listę liczb parzystych w zadanym zakresie.
•
indIndexOf
– podobnie jak
ind
, ale zwraca indeks zgodnego elementu.
30
08/2009
Plik z chomika:
Kapy97
Inne pliki z tego folderu:
2006.12_Ranking popularności języków programowania SDJ_[Jezyki Programowania].pdf
(187 KB)
2009.12_Delphi i C++Builder 2010_[Jezyki Programowania].pdf
(684 KB)
2009.08_Język skryptowy Lua _[Jezyki Programowania].pdf
(703 KB)
2009.08_WS-BPEL Instrumentacja procesów biznesowych_[Jezyki Programowania].pdf
(1645 KB)
2009.08_Groovy na pohybel Javie, z miłością do Javy–wprowadzenie do języka_[Jezyki Programowania].pdf
(1233 KB)
Inne foldery tego chomika:
Algorytmy
Antyhaking
Aplikacje Biznesowe
Aspekty
Bazy Danych
Zgłoś jeśli
naruszono regulamin