+ All Categories
Home > Documents > Artigo Sobre Groovy - Projeto de Paradigm As

Artigo Sobre Groovy - Projeto de Paradigm As

Date post: 03-Jul-2015
Category:
Upload: lucianomedeiros
View: 1,035 times
Download: 2 times
Share this document with a friend
Popular Tags:
42
Análise Sistemática da Linguagem Groovy Anna C. S. Medeiros, Leandro Figueiredo Alves, Luciano Medeiros, Rafael de Castro [email protected], [email protected], [email protected], [email protected] Departamento de Informática – Universidade Federal da Paraíba (UFPB) João Pessoa – PB – Brasil Abstract. This article aims to systematically analyze the Groovy scripting language, designed to generate Java interpreted code in order to explain the features and paradigms of the language and display some new concepts introduced by the same, demonstrating these concepts with examples and comparing with its "mother language" Java. Resumo. Este artigo visa analisar sistematicamente a linguagem script Groovy, desenvolvida para gerar código interpretado para Java, visando explanar as funcionalidades e paradigmas da linguagem e mostrar alguns novos conceitos introduzidos pela mesma, demonstrando esses conceitos com exemplos e comparando com sua “linguagem mãe” Java. 1. INTRODUÇÃO Ao contrário do Microsoft .Net, Java (linguagem e plataforma) não foi criada visando o uso de várias linguagens para gerar código interpretado (bytecodes em Java, MSIL - Microsoft
Transcript
Page 1: Artigo Sobre Groovy - Projeto de Paradigm As

Análise Sistemática da Linguagem Groovy

Anna C. S. Medeiros, Leandro Figueiredo Alves, Luciano Medeiros, Rafael de Castro

[email protected], [email protected],

[email protected], [email protected]

Departamento de Informática – Universidade Federal da Paraíba (UFPB)

João Pessoa – PB – Brasil

Abstract. This article aims to systematically analyze the Groovy scripting language,

designed to generate Java interpreted code in order to explain the features and

paradigms of the language and display some new concepts introduced by the same,

demonstrating these concepts with examples and comparing with its "mother

language" Java.

Resumo. Este artigo visa analisar sistematicamente a linguagem script Groovy,

desenvolvida para gerar código interpretado para Java, visando explanar as

funcionalidades e paradigmas da linguagem e mostrar alguns novos conceitos

introduzidos pela mesma, demonstrando esses conceitos com exemplos e

comparando com sua “linguagem mãe” Java.

1. INTRODUÇÃO

Ao contrário do Microsoft .Net, Java (linguagem e plataforma) não foi criada visando o uso de

várias linguagens para gerar código interpretado (bytecodes em Java, MSIL - Microsoft

Intermediate Language - em .Net). Com os anos, a comunidade Java criou suas próprias

ferramentas para compensar este fato, na forma de linguagens que geram bytecodes

compatíveis com os produzidos pelo compilador da linguagem Java.

Groovy é uma destas linguagens, talvez a mais conhecida. É um projeto de Software

Livre hospedado na Codehaus responsável por outros projetos como XStream, Pico/Nano

Container, AspectWerkz, ActiveMQ, JMock, Drools e tantos outros. A linguagem Groovy é

padronizada pela JSR 241.

Page 2: Artigo Sobre Groovy - Projeto de Paradigm As

O grande foco de Groovy é a produção de scripts, como os feitos em Bash ou Perl,

mas a linguagem é poderosa o suficiente para ir muito além. Alguns programas podem exigir

que rotinas sejam configuráveis e a maioria dos grandes sistemas empresariais, como ERPs e

outros sistemas vendidos como produtos, permite um alto nível de personalização por cliente.

Imagine um software de frente de caixa que precisa aceitar promoções definidas pelo time de

marketing várias vezes por ano.

Na maioria das vezes estas configurações são implementadas com algum nível de

parametrização em arquivos de configuração, mas quando existe uma mudança grande (como

uma promoção "compre dois produtos do lote ABC-001 e leve mais um") geralmente o

desenvolvedor precisa codificar esta em Java e fazer outro deploy da aplicação. Com

linguagens de script, isso pode ser alterado dinamicamente. Neste artigo, veremos suas

principais características.

2. HISTÓRICO

No dia 29 de agosto de 2003 James Strachan publicou em seu blog o primeiro artigo sobre

aquilo que viria a ser o Groovy. Ele deixava bem claro as suas intenções na época: “minha

idéia inicial é fazer uma pequena linguagem dinâmica, que seja compilada diretamente em

classes Java e que tenha toda a produtividade elegante encontrada em Ruby e Python, mas que

permita reusar, estender, implementar e testar código Java já existente”.

James procurava uma linguagem dinâmica para desenvolver em plataforma Java, e

em seu post ele deixava claro que as opções da época não eram interessantes. Ele não queria

apenas uma linguagem dinâmica, mas sim algo que pudesse ser integrado ao que ele já tinha

pronto em Java, algo que acelerasse seu desenvolvimento e que não o obrigasse a jogar tudo o

que tinha de código Java já pronto e testado (e em produção) no lixo. Enfim, ele queria algo

que não existia na época.

James então uniu-se a Bob McWhirter e juntos fundaram o projeto Groovy em 2003.

Logo, com um grupo de pessoas que compartilhavam da mesma idéia, iniciaram o

desenvolvimento da linguagem. Foi em 2004, com a fundação do GroovyOne e a entrada de

outros desenvolvedores que tudo decolou. Foi criada a Groovy Language Specification (GLS)

Page 3: Artigo Sobre Groovy - Projeto de Paradigm As

e o kit para testes de compatibilidade (o TCK), além do parser básico da linguagem. O

embrião do projeto estava pronto e a partir daí não teria mais como voltar atrás.

Groovy evoluiu desconhecido por algum tempo, e até dezembro de 2007 várias

versões foram lançadas sob o número 1.1.x. Em 7 de dezembro de 2007 a versão final da

família 1.1 foi lançada, e então nomeada Groovy 1.5 devido às diversas modificações

realizadas na mesma. Hoje a linguagem é uma especificação do JCP (JSR 241) e é

considerada a segunda linguagem oficial da plataforma.

Ao contrario do que alguns pensam, Groovy não é um concorrente do Java, mas uma

ferramenta de apoio e de produtividade.

3. SISTEMA DE TIPOS

Ao contrário de Java em que possuímos tipos primitivos e não primitivos, em Groovy tudo é

considerado objeto. Os tipos compostos são abstraídos com as operações avançadas de

Orientação a objeto, como herança, porque não existem tipos primitivos.

Tornar atividades comuns mais convenientes é uma das principais promessas do

Groovy. Consequentemente, Groovy torna até mesmo os mais simples tipo de dados em

objetos de primeira classe e implementa operadores como chamadas de métodos para fazer os

benefícios da orientação à objetos disponíveis.

A Conveniência ao programador é aumentada permitindo uma variedade de meios

para declarações literais de string, seja através das flexíveis declarações Gstring ou com a

sintax para situações onde escape extra é indesejável, como padrões de expressão regulares.

Gstrings contribuem para outro dos pilares centrais do Groovy: código conciso e

expressivo. Isto permite ao leitor uma clara visão do valor corrente da string, sem ter que

passar por reinos de concatenação de strings ou trocar de formatos de string e os valores lá

contidos.

A escolha entre tipagem estática ou dinâmica é também uma das chaves dos

benefícios do Groovy. A internet está cheia de discussões sobre qual a melhor tipagem. Em

outras palavras, não existem bons argumentos para nenhuma posição. Sistemas de tipos

estáticos promovem mais informação para otimização, checam melhor na hora da compilação,

Page 4: Artigo Sobre Groovy - Projeto de Paradigm As

e promovem melhor para suporte para IDE. Também revelam informações adicionais sobre o

significado de variáveis ou parâmetros de métodos, além de permitir sobrecarga de métodos.

Tipagem dinâmica, não somente é conveniente para o programador mais relaxado

que faz script do tipo ad-hoc, como também é confiável e economiza linhas de programação.

Groovy é uma linguagem mista, onde se pode obter os benefícios da tipagem estática ou os

benefícios da tipagem dinâmica.

Em se tratando de números, no que diz respeito à conversão de tipos e gerenciamento

com precisão, Groovy promove um uso intuitivo, até mesmo para não-programadores. Isto se

torna particularmente importante quando scripts Groovy são usados para configuração

inteligente de grandes sistemas onde usuários empresários provêem fórmulas.

Strings, expressões regulares e números, todos são beneficiados por vários métodos

que o GDK(Kit de Desenvolvimento Groovy) introduz em cima do JDK.

Os designers da linguagem Groovy estão bem cientes dos conceitos que estão

raramente longe das mentes de um programador

O trabalho foi desenvolvido baseado em uma visita feita a empresa em questão onde

foi feita uma entrevista com o dono da empresa Renato Silva Rodrigues, com perguntas

formuladas para abranger todo o conteúdo abordado na disciplina Administração de

Empresas, afim de construir o seguinte relatório a partir das respostas obtidas sobre o

funcionamento da empresa, podendo assim discuti-las de acordo com o assunto abordado em

sala de aula.

4. EXPRESSÕES

Uma expressão é uma construção que é avaliada e produz um valor.

Na linguagem Groovy temos os seguintes as seguintes formas fundamentais de

expressões:

Literais;

Construções;

Chamadas de Funções;

Expressões Condicionais;

Acesso de Constante e de Variável.

Page 5: Artigo Sobre Groovy - Projeto de Paradigm As

A linguagem Groovy não possui expressões iterativas, mas possui, além das outras

formas fundamentais de expressões, expressões regulares.

4.1. Literais

O tipo mais simples de expressão. Denota um valor fixo de algum tipo.

Tem-se como exemplos de literais para a linguagem Groovy:

125

1.23

“Hello”

“““first line,

second line

and third line”””

4.2. Construções

É uma expressão que construe um valor compost a partir dos seus valores components. Em

Groovy tem-se construções tais como: List, Map, Ranges e Objetos.

4.2.1. List

É uma estrutura usada para armazenar uma coleção de itens de dados.

Definição de uma lista:

def numbers = [11, 12, 13, 14]

Acesso do elemento de índice 0 (11):

numbers [0]

4.2.2. Map

Coleção de referências de objetos desordenada.

Definição de um map com integers como chave e a lista de seus divisores:

Page 6: Artigo Sobre Groovy - Projeto de Paradigm As

def divisors = [4 : [2]. 6 : [3, 2]. 12 : [6, 4, 3, 2]]

Acessar um elemento do map com a chave 6 ([3, 2]):

divisors[6]

4.2.3. Ranges

Utilizado para especificar uma seqüência de valores. Exemplo:

‘A’..‘D’ //A, B, C e D

4.2.4. Objetos

Para a utilização de um objeto é necessário definir suas propriedades em uma classe. A

estrutura de uma classe em Groovy é a seguinte:

class Account{

//Atributos

def number

def balance

//Método

def credit(amount){

balance += amount

}

}

A instanciamento do objeto:

def acc = new Account(number : ‘ABC123’. Balance : 1200)

4.3. Chamada de Funções

Uma chamada de função computa um resultado aplicando um método a um ou mais

argumentos. Exemplo de método:

Page 7: Artigo Sobre Groovy - Projeto de Paradigm As

def getAccountBalance(number){

def acc = this.findAccount(number)

return (acc == null) ? null : acc. Balance

}

Exemplo de chamada de função (objeto que possui o método: bk):

def balance = bk.getAccountBalance(‘ABC123’)

Um operador também denota uma função:

def number = 2 * 3

4.4. Expressões condicionais

Computa um valor que depende de uma condição. Estrutura em Groovy:

expr ? expr1 : expr2

Se expr é true então o valor de expr1 é o resultado, se é false o valor de expr2 é o

resultado.

4.5. Acesso de constante e de variável

Um acesso de constante é uma referência a uma constante e um acesso de variável é uma

referência a uma variável. Exemplo de constante e variável, respectivamente:

final String CONSTA = ‘a’

String varA = ‘a’

4.6. Expressões regulares

Uma expressão regular é um padrão usado para encontrar substrings em texto. Groovy suporta

expressões regulares nativamente utilizando a expressão ~“regex”, onde o texto dentro das

aspas representa a expressão regular.

Page 8: Artigo Sobre Groovy - Projeto de Paradigm As

Exemplo:

Def regex = ~‘cheese’

Quando o operador do Groovy =~ aparece como um predicado em comandos if e

while, o String da esquerda é comparado com a expressão regular da direita. Os seguintes

exemplos retornam true:

‘cheesecake’ =~ ‘cheese’

‘cheesecake’ =~ regex

O operador ==~ requer uma equivalência perfeita.

Em uma expressão, dois caracteres posicionais são usados para denotar o começo e o

final de uma linha: ^ e $:

def rhyme = ‘Humpty Dumpty Sat on a wall’

rhyme =~ ‘^Humpty’

rhyme =~ ‘wall$’

Expressões regulares podem incluir também quantificadores:

+ representa uma ou mais vezes, aplicado ao elemento precedente;

* representa zero ou mais ocorrências;

? denota zero ou uma vez;

{ } é utilizado para definir um específico número de ocorrências do caractere

precedente.

Exemplos dos quantificadores:

‘aaaaab’ =~ ‘a*b’

‘b’ =~ ‘a*b’

‘aaaaab’ =~ ‘a{5}b’

Page 9: Artigo Sobre Groovy - Projeto de Paradigm As

O símbolo . pode representar qualquer caractere. É possível definir um grupo de

caracteres possíveis com o uso de [ ], criando assim uma classe de caracteres. Seqüências de

letras ou números podem ser representadas por -, como: [a-z].

O complemento de uma classe de caracteres é denotado por um ^ dentro dos

colchetes: [^a-z].

5. COMANDOS

Um comando é uma construção do programa que será executada para atualizar variáveis.

A linguagem Groovy possui os seguintes comandos:

Atribuições;

Chamadas de Método;

Comandos Sequenciais;

Comandos Condicionais;

Comandos Iterativos.

Groovy proporciona uma facilidade na iteração de coleções, o método each, que será

mostrado mais a frente.

5.1. Atribuições

Uma variável é atualizada para armazenar um valor. Esse comando tem a forma: V = E, onde

V é um acesso da variável e E é uma expressão que retorna uma valor para ser armazenado.

Exemplo:

def count = 0

5.2. Chamadas de métodos

É um comando que alcança seu efeito aplicando um método para alguns argumentos. Classe

usada para o próximo exemplo:

Class Account{

def balance

Page 10: Artigo Sobre Groovy - Projeto de Paradigm As

def credit(amount){

balance += amount

}

}

Exemplo de chamada de método para a classe Account:

acc.credit(50) //Atualiza a variável balance somando-a ao valor do parâmetro

5.3. Comandos sequenciais

Um comando seqüencial especifica dois ou mais programas serão executados em seqüência.

Um comando seqüencial pode ser escrito da seguinte forma: C1; C2 (C1 executa primeiro que

C2).

Exemplo em Groovy:

print ‘Hello’; print ‘!!!’

5.4. Comandos condicionais

Possui dois ou mais subcomandos, dos quais exatamente um é escolhido para ser executado.

5.4.1. Comando if

Forma geral do comando if:

if(condição){

comando1a

...

} else{

comando2a

...

}

Page 11: Artigo Sobre Groovy - Projeto de Paradigm As

Se a condição for verdadeira é executado o corpo do bloco if, se for falsa é executado

o bloco else.

5.4.2. Comando switch

Sintaxe:

Switch(expressão){

case expressão 1:

comando 1a

...

...

case expressão N:

comando Na

...

default:

comando Da

...

}

A expressão entre parênteses é avaliada, e seu resultado é comparado com as

expressões dos cases. Se alguma expressão dos cases for equivalente a expressão, todos os

comandos do case com a expressão equivalente até o final são executados. Se não houver

nenhum equivalente então se executa os comandos do default.

Para executar só um case, pode se usar o comando break, colocando-o no final do

bloco de comandos do case, que quando o comando break é executado sai-se do switch.

5.5. Comandos iterativos

Um comando iterativo tem um subcomando que é executado repetidamente.

Page 12: Artigo Sobre Groovy - Projeto de Paradigm As

5.5.1. Comando while

Sintaxe do comando while:

while(condição){

comando 1

comando 2

...

}

Enquanto a condição for verdadeira os comandos no corpo do while serão

executados.

5.5.2. Comando for

Em Groovy o comando for pode ser usado com um Range, uma coleção ou um String.

Sintaxes:

for(variable in range){

...

}

for(variable in collection){

...

}

for(variable in string){

...

}

Exemplos:

Page 13: Artigo Sobre Groovy - Projeto de Paradigm As

//Range

def LIMIT = 10

for(count in 1..LIMIT)

println “count: ${count}”

//List

for(count in [11, 12, 13, 14])

println “count: ${count}”

//Map

def staff = [‘Ken’:21, ‘John’:25, ‘Sally’:22] //Nome e idade

def totalAge = o

for(staffEntry in staff)

totalAge += staffEntry.value

//String

def name= ‘Kenneth’

def listOfCharacters = [ ]

for(letter in name)

listOfCharacter<<letter

5.5.3. Método each

Em Java temos o seguinte modo de iterar uma coleção:

for (Iterator collection.iterator(); iterator.hasNext(); ){

MyClass obj = (MyClass) iterator.next();

// do something with obj

}

Groovy proporciona um modo mais simples de se fazer isso:

collection.each { /* do something with it */}

Page 14: Artigo Sobre Groovy - Projeto de Paradigm As

6. FORMAS DE DECLARAÇÃO E BLOCOS

Assim como em Java, as estruturas de bloco são definidas entre ‘{’ e ‘}’. Assim como Java,

Groovy usa os escopos estáticos, suportando também blocos aninhados. Essas estruturas

podem ser classe, interface, inicializadores de objeto ou estáticos ou corpos de métodos,

podem aparecer com as palavras chave Groovy como if, else, synchronized, for, while, switch,

try, catch e finally. Todas as ocorrências são closures.

6.1. Closures

Um closure seria um pedaço de código dobrado como um objeto. Ele age como um método

que pode conter parâmetros e pode retornar um valor. É um objeto normal em que você pode

estar rodando um código Groovy, então não há nada particularmente estranho que poderia

estar fazendo com um objeto closure. É apenas um objeto. [1] Eles podem ser armazenados

em variáveis, podem ser passados adiante e pode-se chamar métodos neles. Sendo objetos,

closures podem também ser retornados de um método.

O mecanismo de escopo do Groovy é também significativamente mais flexível e

poderoso, enquanto remove o excesso de código que as classes de Java introduzem. Veja o

exemplo de uma classe Java, com os elementos importantes em negrito:

// Java

interface ResourceUser {

public void use (Resource resource)

}

resourceHandler.handle(new ResourceUser() {

public void use (Resource resource){

resource.doSomething()

}

O equivalente Groovy deste código revela todas as informações necessárias sem

qualquer desperdício:

resourceHandler.handle { resource -> resource.doSomething() }

Page 15: Artigo Sobre Groovy - Projeto de Paradigm As

6.2. Usando closures

Chamando um closure: Suponha que nós tenhamos uma referencia x apontando para um

closure; nós podemos chamá-la com um x.call() ou simplesmente x(). Quaisquer argumentos

para a chamada do closure vão sempre entre parênteses:

def adder = { x, y -> return x+y }

assert adder(4, 3) == 7

assert adder.call(2, 6) == 8

A classe groovy.lang.Closure é uma classe ordinária, apesar de ser uma com

poder extraordinário e suporte extra de linguagem. Ela tem vários métodos disponíveis além

de call. A seguir são apresentados os mais importantes.

6.2.1. Reagindo na Contagem de Parâmetro

Um exemplo de quão útil é reagir na contagem de parâmetro de um closure é seu método each

do map. Ele passa tanto um objeto Map.Entry ou chave e valor separados no closure dado,

dependendo se o closure leva um ou dois argumentos. Você pode conseguir a informação

sobre a contagem esperada de parâmetros (e tipos, se declarados) chamando-se o método de

closure getParameterTypes:

def caller (Closure closure) {

closure.getParameterTypes().size()

}

assert caller { one -> } == 1

assert caller { one, two -> } == 2

Isso permite a luxúria de suportar closures com diferentes estilos de parâmetro,

adaptados às necessidades do caller.

Page 16: Artigo Sobre Groovy - Projeto de Paradigm As

6.2.2. Como Fazer Curry Favor com um Closure

Currying é uma técnica inventada por Moses Schönfinkel e Gottlob Frege, e nomeada pelo

lógico Haskell Brooks Curry (1900..1982), um pioneiro em programação funcional. A idéia

básica é tomar uma função com múltiplos parâmetros e transformá-la em uma função com

menos parâmetros, fixando alguns dos valores. Um exemplo clássico é escolher algum valor

arbitrário n e transformar uma função que some dois parâmetros em uma função que leva um

único parâmetro e adicionar n a ele.

No Groovy, o método Closure`s curry retorna um clone do closure atual, tendo como

limite um ou mais parâmetros para um valor dado. Parâmetros são limitados pelos argumentos

do curry da esquerda para a direita. O exemplo sequinte mostra uma implementação:

def adder = { x, y -> return x+y }

def addOne = adder.curry (1)

assert addOne (5) == 6

Desta maneira reutilizamos o mesmo closure agora para soma geral. Nós chamamos

o método curry nele para criar um novo closure, que age como um simples adicionador, mas

com o valor do primeiro parâmetro sempre fixado em 1. Finalmente, checa-se o resultado.

6.2.3. Classificação pelo Método isCase

Closures implementam o método isCase para fazer os closures funcionarem como

classificadores em grep e switch. Neste caso, o argumento respectivo é passado no closure, e

ao chamar o closure precisa-se avaliar a um valor Boolean Groovy. Como se pode ver em:

assert [1, 3, 3].grep{ it<3 } == [1, 2]

switch (10) {

case { it%2 == 1 } : assert false

}

Page 17: Artigo Sobre Groovy - Projeto de Paradigm As

Isso nos permite classificar por lógica arbitrária. Novamente, isso é possível apenas

porque closures são objetos.

6.2.4. Métodos Remanescentes

Em favor da completude, é preciso dizer que closures suportam o método clone no sentido

usual Java.

O método asWritable retorna um clone do closure atual que tem um método

adicional writeTo(Writer) para escrever o resultado de uma chamada de closure diretamente

ao Writer dado.

6.2.5. Escopo

O que está disponível dentro de um closure, como:

Variáveis locais;

O que this se refere;

Campos e métodos acessíveis;

Todo o closure é limitado pelo bloco, definido entre ‘{‘ e ‘}’.

6.2.6. Estruturas de Controle

Avaliando testes Boolean: E expressão de um teste Boolean pode ser de qualquer tipo (não-

Void, “vazio”). Isso pode se aplicar a qualquer objeto. O Groovy decide se considera a

expressão como sendo falsa ou verdadeira aplicando as regras mostradas na tabela seguinte,

baseada em resultados do tipo do tempo de execução. As regras são aplicadas na ordem dada,

e, uma vez que uma regra coincida, ela determina completamente o resultado.

Tabela 1. Tipos de runtime e os critérios de avaliação exigidos

Tipo runtime Critério de avaliação exigido

Boolean Valor Boolean correspondente é verdadeiro

Matcher O combinador tem uma combinação

Collection A coleção não está vazia

Map O mapa não está vazio

String, GString A string não está vazia

Page 18: Artigo Sobre Groovy - Projeto de Paradigm As

Number, Character O valor não é zero

Nenhum dos acima A referencia ao objeto não é nula

Exemplos:

// Valores Boolean são triviais:

assert true

assert !false

// Matches precisam combinar (match)

assert (‘a’ =~ / ./)

assert ! (‘a’ =~ /b/)

// Coleções não podem estar vazias

assert [1]

assert ![]

// Mapas não podem estar vazios

assert [‘a’ : 1]

assert ![:]

// Strings não podem estar vazios

assert ‘a’

assert !’’

// Números de qualquer tipo não podem ser zero

assert 1

assert 1.1

assert 1.2f

assert 1.3g

Page 19: Artigo Sobre Groovy - Projeto de Paradigm As

assert 2L

assert 3G

assert !0

// Qualquer outro valor não pode ser nulo

assert new Object()

assert !null

6.2.7. Estruturas Condicionais

Avaliam um teste Boolean e fazem uma escolha sobre o que fazer a seguir, baseado se o

resultado foi verdadeiro ou falso. If e if/else funcionam exatamente como em Java, e as

limitações do bloco também são idênticas como em Java.

if (false) assert false // If com uma linha

if (null)

{ // Bloco que se inicia com uma nova linha

assert false

}

else

{

assert true

}

Operador condicional abreviado ?, também idêntico ao em Java:

def result = (1==1) ? ‘ok’ : ‘failed’

assert result == ‘ok’

6.2.8. Estrutura switch

Também tem construção idêntica ao caso de Java, e sua lógica também é idêntica ao sentido

que a manipulação lógica recai no próximo caso a não ser que tenha saída explícita (com a

terminação break)

Page 20: Artigo Sobre Groovy - Projeto de Paradigm As

def log = ‘’

switch (a) {

case 0 : log += ‘0’

case 1 : log += ‘1’

case 3 : log += ‘2’ ; break

case 4 : log += ‘default’

}

assert log == ‘12’

6.2.9. Switch com Classificadores

Um classificador é eleito como uma switch caso ele implemente o método isCase. De modo

genérico, temos:

switch (candidate) {

case classifier1 : handler1() ; break

case classifier2 : handler2() ; break

default : handlerDefault()

}

Que é aproximadamente equivalente aos comandos condicionais:

if (classifier1.isCase(candidate)) handler1()

else if (classifier2.isCase(candidate)) handler2()

else handlerDefault()

Isso permite classificações expressivas e mesmo alguns usos pouco convencionais

com classificadores misturados. Diferente dos casos de constantes do Java, o candidato pode

muito mais do que um classificador. Isso significa que a ordem dos casos é importante em

Groovy, visto que ele não afeta o comportamento em Java. A listagem a seguir dá um

Page 21: Artigo Sobre Groovy - Projeto de Paradigm As

exemplo de múltiplos tipos de classificadores. Depois de ter checado que o nosso número 10

não é zero, não está na esclaa 0..9, nem na lista [8,9,11], nem é do tipo Float e não é uma

integral múltipla de 3, nós finalmente descobrimos que ele é feito de dois caracteres.

switch (10) {

case 0 : assert false ; break

case 0..9 : assert false ; break

case [8,9,11] : assert false ; break

case Float : assert false ; break // Caso de tipo

case {it%3 == 0} : assert false ; break // Caso de closure

case ~/../ : assert true ; break // Caso de expressão regular

default : assert false ; break

}

Para aumentar o poder da construção switch, é essencial saber as implementações

isCase disponíveis. A seguir há uma lista das implementações mais conhecidas no GDK:

Tabela 2. Lista das implementações mais conhecidas no Groovy Development Kit

Classe a.isCase(b) implementado como

Object a.equals(b)

Class a.isInstance(b)

Collection a.contains(b)

Range a.contains(b)

Pattern a.matcher(b.toString()).matches()

String A==null && b==null || a.equals(b)

Closure a.call(b)

6.2.10. Looping com while

Construção como sua contraparte Java. A única diferença é a vista anteriormente: o poder das

expressões de teste Boolean do Groovy.

def list = [1, 2, 3]

while (list) {

Page 22: Artigo Sobre Groovy - Projeto de Paradigm As

list.remove(0)

}

Assert list == []

6.2.11. Looping com for

O Groovy torna o loop for uma iteração com maior facilidade, apesar de ser amplamente

utilizado, sua estrutura não é facilmente expressa. Loops Groovy seguem a seguinte estrutura:

for (variable in iterable) { body }

em que variable pode opcionalmente ter um tipo declarado. O loop Groovy for itera sobre a

iterável. Iteráveis usafas frequentemente são escalas, coleções, mapas, arrays, iteradores e

enumeradores. De fato, qualquer objeto pode ser um iterável.

Exemplos de loops for:

// Tipificado, sobre escala de campo de texto, sem chaves

def store = ‘’

for (String i in ‘a’..c’’) store += i

assert store == ‘abc’

// Não tipificado, sobre lista e coleções, chavesstore = ‘’

for (i in [1, 2, 3]) {

store += i

}

assert store == ‘123’

// Não tipificado, sobre IntRange meio-exclusiva, chaves

def myString == ‘Equivalent do Java’

Page 23: Artigo Sobre Groovy - Projeto de Paradigm As

store = ‘’

for (i in 0 ..< myString.size() ) {

store += myString[i]

}

// Não tipificado, sobre campo de texto como coleção, chaves

assert store == myString

store = ‘’

for (i in myString) {

store += i

}

assert store == myString

Todos os loops Groovy possuem os terminadores return, break e continue, como em

Java, com a única diferença que a palavra-chave return é opcional para a última expressão em

um método ou closure. Se for omitida, o valor de retorno vai ser o mesmo valor da última

expressão.

Sobre tipos, como já citado, todos os tipos são tratados como objetos, e as

declarações são tal qual em Java, porém, Groovy oferece a escolha de atribuir tipos

explicitamente exatamente e também declarações de tipos estáticos opcionais e o tipo

dinâmico usado em tempo de execução. A palavra chave def é usada para indicar que nenhum

tipo particular é exigido.

Tabela 3. Declaração de tipos

Indicação Tipo de valor Comentário

def a = 1 java.lang.Integer Tipo implícito

def b = 1.0f java.lang.Float

int c = 1 java.lang.Integer Tipo explícito usando os

float d = 1 java.lang.Float

Page 24: Artigo Sobre Groovy - Projeto de Paradigm As

tipos de dados primitivos

integer e = 1 java.lang.Integer Tipo explícito usando nomes

de tipos de referenciaString f = ‘1’ java.lang.String

Assim como em Java, Groovy suporta declarações de tipos (classes, interfaces),

métodos, variáveis, constantes, pacotes e declarações seqüenciais e recursivas, porém não

possui declarações colaterais. As estruturas das declarações se assemelha a Java, tanto de

objetos, classes e interfaces quanto de métodos, e as duas liguagens possuem as mesmas

estruturas bindables (valores, variáveis locais, instancia e variáveis de classes, métodos,

classes e pacotes).

Declarações de métodos seguem os mesmos conceitos que os para variáveis: Os

modificadores usuais Java podem ser usados; declarar um tipo de retorno é opcional; e, se

nenhum modificador ou tipo de retorno for fornecido, a palavra chave def preenche a lacuna.

Quando a palavra-chave é usada, o tipo de retorno é julgado não ter sido escolhido (apesar de

que ele ainda pode não ter tipo de retorno, equivalente a void). A visibilidade padrão dos

métodos é pública, e a passagem de objetos nos parâmetros é por referencia, assim como em

Java, e os parâmetros podem ou não ser definidos:

class SomeClass {

static void main (args){ // public implícito

def some = new SomeClass()

some.publicVoidMethod()

assert ‘hi’ == some.publicUntypedMethod()

assert ‘ho’ == come.publicTupeMethod()

combinedMethod() // Chama o método estático da classe atual

}

void publicVoidMethod() {

}

def publicUntypedMethod() {

return ‘hi’

Page 25: Artigo Sobre Groovy - Projeto de Paradigm As

}

String publicTypedMethod() {

return ‘ho’

}

protected static final void combinedMethod() {

}

static method(String args) {

return ‘typed’

}

static method (arg1, Number arg2) { //sobrecarga de métodos

return ‘two args’

}

}

7. PROCEDIMENTOS DA LINGUAGEM

 Como citado anteriormente, os procedimentos em Groovy se dão da mesma forma

que em Java (métodos), e acessados da seguinte forma:

objectReference.methodName()

Porém, este formato impõe restrições para nomes de método; por exemplo, eles

podem não conter caracteres especiais, como menos (-) ou ponto (.). Contudo, o Groovy lhe

permite usar esses caracteres em nomes de métodos se você colocar aspas ao redor do nome:

objectReference.‘my.method-Name’()

O objetivo dessa característica é suportar usos onde o nome do método de uma

chamada se torna parte da funcionalidade.

Page 26: Artigo Sobre Groovy - Projeto de Paradigm As

7.1. Desreferencia segura com o operador ?

Quando uma referencia não aponta nenhum objeto específico, seu valor é null. Quando se

chama um método ou se acessa um campo em uma referencia nula, um NullPointerException

(NPE) é jogado. Isso é útil para proteger o código de trabalhar em pré-condições indefinidas,

mas pode facilmente tomar o caminho do código do “melhor esforço” que deve ser executado

para referencias válidas e apenas silenciar outras de outra forma.

A seguir um exemplo mostra várias aproximações alternativas para proteger o código

de NPE`s. Groovy fornece o operador adicional ?, para desdiferencia segura. Quando a

referencia antes do operador é uma referencia nula, a avaliação da expressão atual pára, e null

é retornado, e a desreferencia segura é a forma mais elegante e compacta, além de expressiva,

comparado com outras soluções:

def map = [ a : [b : [ c : 1 ] ] ]

assert map.a.b.c == 1

if (map && map.a && map.a.x) { // Proteção com if: avaliação de curto-circuito

assert map.a.x.c == null

}

try { // Proteção com try / catch

assert map.a.x.c == null

} catch (NullPointerException npe) {

}

Assert map?.a?.x?.c == null // Desreferencia segura.

Para a aplicação das normas de qualidade dentro da empresa, a empresa disponibiliza

treinamento dentro da própria para seus funcionários, e aqueles que realizarem treinamentos

externos (apoiados pela empresa), se responsabilizam por multiplicar o conhecimento aos

outros funcionários ministrando cursos dentro da própria empresa, recebendo pagamento

referente à hora-aula ministrada.

Page 27: Artigo Sobre Groovy - Projeto de Paradigm As

8. GROOVY E ORIENTAÇÃO A OBJETOS

Groovy não apenas realça o Java tornando-o uma linguagem de script, mas também fornece

novas características OO, características de orientação dinâmica a objetos. Definição de

classes em Groovy é quase idêntica ao Java; classes são declaradas usando-se a palavra-chave

class e podem conter campos, construtores, inicializadores e métodos. Métodos e construtores

podem eles próprios utilizar variáveis locais como parte de seu código de implementação.

Scripts são diferentes – oferecendo flexibilidade adicional, mas com algumas restrições,

também. Eles podem conter código, definição de variáveis e métodos assim como definições

de classe.

Definir o tipo de uma variável em Groovy é opcional. Contudo, o identificador não

pode ficar sozinho na declaração. Quando nenhum tipo e nenhum modificador é dado, a

palavra-chave def precisa ser usada como uma substituição, efetivamente indicando que o

campo ou a variável não foi digitada (apesar de que, sob as cobertas, ela será declarada como

do tipo Object).

Exemplo de declaração de classe e de variáveis:

Class SomeClass {

public fieldWithModifier

String typedField

def untypedField

protected field1, field2, field3

private assignedField = new Date()

static classField

public static final String CONSTA = ‘a’, CONSTB = ‘b’

def someMethod(){

def localUntypedMethodVar = 1

int localTypedMethodVar = 1

def localVarWithoutAssignment, andAnotherOne

Page 28: Artigo Sobre Groovy - Projeto de Paradigm As

}

}

A relação entre arquivos e declarações de classe não é fixa como no Java. Arquivos

Groovy podem conter qualquer numero ou declarações de classe públicas de acordo com as

seguintes regras:

Se um arquivo Groovy não contém declaração de classe, ele é

manipulado como um script; isto é, ele é transparentemente dobrado em uma classe do

tipo Script. Essa classe gerada automaticamente tem o mesmo nome do arquivo de

script fonte (sem a extensão). O conteúdo do arquivo é dobrado em um método run, e

um método adicional é construído para facilmente inicializar o script.

Se um arquivo Groovy contém exatamente uma declaração de classe

com o mesmo nome do arquivo (sem a extensão), então há a mesma relação um-a-um

que em Java.

Um arquivo Groovy pode conter múltiplas declarações de classe de

qualquer visibilidade, e há uma regra de reforço que qualquer uma delas precisa

coincidir com o nome do arquivo. O compilador groovyc felizmente cria arquivos

*.class para todas as classes declaradas em tal arquivo. Se você quer invocar seu script

diretamente, por exemplo utilizando Groovy na linha de comando ou dentro de um

IDE, então a primeira classe dentro de seu arquivo deve ter um método main.

Um arquivo Groovy pode conter declarações de classe misturadas e

código de script. Nesse caso, o código de script irá se tornar a principal classe a ser

executada, então não declare uma classe por si tendo o mesmo nome de um arquivo

fonte.

A orientação a objetos em Groovy traz como pontos positivos o encapsulamento dos

dados, provendo assim maior segurança da informação, e o reuso de código, como muitos

falam, não é necessário “reinventar a roda” toda vez que for utilizá-la.

9. SEQÜENCIADORES

Em relação aos seqüenciadores, Groovy é muito similar ao Java. Assim como em Java,

Groovy não permite o uso de goto, apesar de que ela seja uma palavra reservada. Quanto a

Page 29: Artigo Sobre Groovy - Projeto de Paradigm As

return, break e continue, a diferença é que a palavra-chave return é opcional para a última

expressão em um método ou closure. Se ela for omitida, o valor de retorno é aquele da última

expressão. Métodos com tipo explícito de retorno void não retornam um valor.

Exemplo de break e continue:

def a = 1

while(true) {

a++

break

}

assert a == 2

for(i in 0..10) {

if(i==0) continue

a++

if(i > 0) break

}

assert a == 3

Manipulação de exceções é exatamente como em Java e segue a mesma lógica.

Como no Java, você pode especificar uma sequência completa throw/try-catch-finally de

blocos, ou apenas try-catch, ou apenas try-finally. Diferente das outras estruturas de controle,

chaves são exigidas ao redor dos corpos de bloco contendo ou não mais do que uma

indicação. A única diferença entre Java e Groovy em termos de exceções, é que declarações

de exceções na assinatura do método são opcionais, mesmo para exceções verificadas.

Exemplo de throw, try, catch e finally:

def myMethod() {

throw new IllegalArgumentException()

}

Page 30: Artigo Sobre Groovy - Projeto de Paradigm As

def log = []

try {

myMethod()

}catch(Exception e) {

log << e.toString()

}finally {

log << 'finally'

}

assert log.size() == 2

Apesar da tipificação opcional no resto do Groovy, um tipo é mandatário na

expressão catch.

Não há aviso em tempo de compilação ou de execução do Groovy quando exceções

checadas não são declaradas. Quando uma exceção checada não é manipulada, é propagado

que a execução pára como uma RuntimeException.

10. CONCLUSÃO

A linguagem Groovy é uma excelente ferramenta para gerar código interpretado em Java, e

traz algumas funcionalidades interessantes na programação usual como o suporte nativo a

listas e mapas, e também expressões regulares, além de ter suporte e acesso a qualquer API de

Java, uma das linguagens mais usuais. Porém, um dos grandes benefícios de uma linguagem

script para a Java Virtual Machine é a possibilidade de integrar um programa Java com scripts

e Groovy.

Porém, a linguagem Groovy também possui algumas deficiências, como

performance. Não espere de um script Groovy uma performance como a de um programa

Java. A equipe do projeto está trabalhando em seus compiladores, mas a performance quase

sempre vai ser inferior a de uma aplicação normal.

Depurar um programa em Groovy costuma ser meio frustrante. As mensagens de erro

retornadas pelo compilador podem não parecer ter sentido algum (algo que realmente deve ser

Page 31: Artigo Sobre Groovy - Projeto de Paradigm As

melhorado), mas muito disso se deve á sintaxe relaxada da linguagem (quando se tem tantas

opções, é difícil dizer quando algo está errado).

Groovy possui plugins para as mais famosas IDE`s para Java, porém ainda em

estágio inicial, porém não comprometendo sua usabilidade.

REFERÊNCIAS

[1] KÖNIG, Dierk; GLOVER, Andrew; LAFORGE, Guillaume; SKEET, Jon. Groovy in Action.

Nova York, NY. Manning Publications Co., 2007.

[2] BARCLAY, Kenneth; SAVAGE, John. Groovy Programming an Introduction for Java Developers.

São Francisco, CA. Morgan Kaufmann Publish, 2007.

[3] WATT, David A.; FINDLAY, William; Programming Languanges Design Concepts, Glasgow, IR.

John Wiley & Sons, Ltd, 2004.


Recommended