Antes de começarmos a trabalhar diretamente com Grails, convém conhecer o básico do Groovy. Afinal de contas, é a linguagem por trás da ferramenta e, mais do que isto, trata-se também de uma linguagem muito interessante para se trabalhar (programadores Java podem ver varios detalhes da linguagem que realmente surpreendem).
O que é Groovy?
No site oficial da linguagem, Groovy é definido como uma “linguagem ágil e dinâmica para a plataforma Java com muitas ferramentas que são inspiradas em linguagens como Python, Ruby e Smalltalk, tornando-as disponíveis aos programadores Java, usando uma sintaxe próxima ao Java”. Se você já programa em Java, portanto, aprender Groovy não será uma tarefa de outro mundo: na realidade, a sintaxe do Groovy é práticamente a mesma que a do Java. A diferença está nos recursos adicionais que a linguagem oferece.
Antes de pormos a mão na massa, no entanto, devemos primeiro nos livrar dos preconceitos ligados ao Groovy, decorrentes da idéia de que trata-se apenas de “mais uma linguagem de script”. Sim: Groovy pode ser usada como uma linguagem de script (e funciona muito bem para este fim), porém também pode gerar código compilado em bytecode que, consequentemente, é integrado de forma transparente a código Java pré existente. Este é um dos pontos fortes da linguagem: código Java chama código Groovy (e vice versa) sem saber em qual linguagem o mesmo foi escrito. Aliás, esta é a tendência da plataforma Java agora: tornar-se mais popular por ser uma plataforma de execução do que uma linguagem de programação.
Sendo assim… os detalhes que importam:
Instalando o Groovy
Se você for usar Groovy apenas com Grails, que por sua vez já se encontra instalado em seu computador, não é necessário fazer nada, pois o Groovy já vêm embutido no Grails.
Caso contrário, a sua instalação é bastante simples. Basta baixar sua última versão em http://groovy.codehaus.org e descompactar o arquivo binário em um diretório de sua escolha. O único requisito para se usar o Groovy consiste na instalação do JDK 1.4 ou posterior. Em seguida, lembre-se de incluir o diretório bin da sua instalação do Groovy no path do seu sistema e também de possuir a veriável de ambiente JAVA_HOME definida em seu sistema.
Diferenças básicas entre código Java e Groovy
Como mencionado anteriormente, a sintaxe do Groovy não é muito diferente da que encontramos em Java. Os principais diferenciais consiste em:
ponto e vírgula opcional: se você for digitar apenas um comando em uma linha, não precisa digitar o ponto e vírgula. No caso de mais de um comando, no entanto, já é necessário.
Exemplo:
println "Sou um comando sem ponto e virgula. Não é legal?" println "Eu já tenho ponto e virgula no final. Sou mais tradicional"; println "Mais de um"; println "comando"; println "na mesma"; println "linha.";
conceito de verdade: Groovy extende o conceito de verdadeiro com o qual estamos habituados a trabalhar em Java. Além do conceito tradicional, Groovy também considera verdadeiro qualquer valor que seja diferente de null, tal como nos exemplos abaixo:
String str = "Sou uma string não nula" String strNula = null if (str) { println "Eu com certeza serei impresso" } if (! strNula) { println "Eu vou ser impresso, pois meu teste consistiu em uma string nula negada!" }
“main opcional”: se estiver trabalhando com Groovy na forma de um script, pode considerar o seu arquivo de código fonte como um main. Tudo o que estiver fora das chaves será considerado código a ser executado, tal como no exemplo abaixo:
println "Veja, sou um script feito em Groovy" boolean maiorQue(int a, int b) { return a < b } println "Reparou como eu simplesmente 'ignorei' a função maiorQue e continuei imprimindo?" [/code] Gerará a saida [code language='java'] Veja, sou um script feito em Groovy Reparou como eu simplesmente 'ignorei' a função maiorQue e continuei imprimindo? [/code] <strong>Tudo é considerado objeto:</strong> ao contrário do Java em que possuimos tipos primitivos e não primitivos, em Groovy tudo é considerado objeto. Sendo assim, os tipos primitivos do Java são convertidos para suas respectivas classes encapsuladoras de forma transparente para o programador, tal como no exemplo abaixo: [code language='java'] int inteiro = 4; print inteiro.toString()
Uma maneira fácil de se habituar a este detalhe da linguagem consiste em compará-la com o autoboxing incluido na linguagem Java a partir da versão 5.
return opcional: a instrução return com a qual já estamos habituados a trabalhar em Java também existe em Groovy. Porém, é opcional. Dada uma função, o valor de retorno do último comando corresponde ao valor de retorno da mesma, tal como no exemplo abaixo:
boolean maiorQuetradicional(int a, int b) { // a maneira "tradicional" de se trabalhar com Java return a > b } boolean maiorQueGroovy(int a, int b) { a > b // bem mais simples! }
sobrescrita de operadores: tal como em C++, em Groovy você também pode sobrescrever os operadores básicos da linguagem, como ++, –, >, etc. (mais sobre isto mais tarde)
Groovy Beans
Groovy facilita muito a vida do desenvolvedor quando o assunto consiste em declaração de beans. Isto porque a linguagem já faz boa parte do trabalho para o desenvolvedor. Você não precisa ficar declarando métodos gets e sets: Groovy faz isto dinâmicamente para você!
Suponhamos que em Java, você precise implementar um bean tal como descrito abaixo:
class Pessoa { private String nome; private String sobrenome; public String getNome() {return this.nome;} public void setNome(String valor) {this.nome = valor;} public String getSobrenome() {return this.sobrenome;} public void setSobrenome(String valor) {this.sobrenome = valor;} }
Em Groovy, você poderia declarar o mesmo bean apenas com o código abaixo:
class Pessoa { String nome; String sobrenome; }
Se o escopo de uma variável é indefinido, Groovy entende que deverá criar dinâmicamente os métodos get e set para cada um dos atributos da classe. Sendo assim, boa parte da sua digitação torna-se desnecessária!
Claro, se quiser pode sobrescrever um get e set para customizar sua classe, tal como no exemplo abaixo:
class Pessoa { String nome; String sobrenome; public String getNome() { return "Sempre me chamarei José!" } }
Tipagem dinâmica
Em Groovy, o tipo das variáveis é definido opcionalmente. Se quiser, você pode defini-lo tal como faria em Java. Caso contrário, pode passar esta tarefa ao Groovy, que ele se vira pra você, tal como no exemplo abaixo:
def a, b a = 5 b = 6 def c = a + b // C será igual a 11. d = c + a + b // D será igual a 22
Para definir uma variável cujo tipo é indefinido, usa-se a seguinte sintaxe:
def [nome da variavel] [especificação do valor opcional]
ou, se preferir, simplesmente
[nome da variavel] [especificação do valor opcional]
Groovy utiliza duck typing para definir os tipos das variáveis. O que é duck typing? Simplesmente isto:
se age como um pato, é um pato.
No caso do Groovy, se uma variável age como sendo de determinado tipo (um número, uma string, etc.), então Groovy irá definir o seu tipo dinâmicamente desta forma.
Strings
Groovy simplifica muito a nossa vida na hora de lidar com strings. As strings com as quais você está a lidar são as mesmas com as quais estava acostumado em Java, porém com alguns detalhes a mais:
Para começar, há três maneiras distintas de se declarar strings em Groovy:
- Áspas simples, como ‘sou uma string em aspas simples’
- Áspas duplas, como em “sou uma string com a qual você já está habituado em Java”
- Áspas triplas, como em
“”” sou uma maneira muito mais
interessante de se lidar com strings que
ocupem bem mais
de uma linha”””
Há uma diferença entre o funcionamento destes três tipos de declaração: strings com áspas duplas e triplas permitem o acoplamento de strings, enquanto strings com áspas simples não. O que nos leva a mais uma útil novidade que Groovy nos trás:
Acoplamento de strings
Em Groovy, você pode incluir o conteúdo de uma variável ou o resultado de uma expressão dentro de uma string sem usar o operador + com o qual estamos acostumados (e irritados) em Java, tal como no exemplo abaixo:
int umInteiro = 5 String aspasDuplas = "Eu gosto do número ${umInteiro}" String aspasTriplas = """Eu gosto muito do número ${umNumero}, mas também curto o seu dobro: ${umNumero + umNumero}"""
Como pode ser visto, a sintaxe é simples. Basta incluir em uma string dupla ou tripla os caracteres ‘${‘ seguidos de uma expressão ou valor e finalizá-lo com um ‘}’.
Closures
Closures é um tópico especial, razão pela qual você podera aprender mais sobre Grails neste link (ainda em produção).
Intervalos, hashes e coleções
Groovy inclui boa parte das Collections do Java na própria sintaxe da linguagem. Não é preciso referenciar o pacote java.util só para usar listas. Groovy já referencia este pacote automaticamente para você e ainda inclui algumas outras novidades tal como descrito abaixo:
Intervalos
Intervalos (no Groovy em Ação, são chamadas de escalas, porém acredito que o termo “intervalo” descreve melhor com o que estamos lidando) consistem em um recurso extremamente útil na linguagem. Você provávelmente é familiar ao senhor abaixo:
for (int i = 0; i < 10; i++) { bla bla bla } [/code] O que temos dentro do loop, na realidade é um intervalo, porém descrito de uma das maneiras mais horrorosas possíveis. A questão que fica agora é: como isto poderia ser melhorado? Veja o código abaixo: [code language='java'] for (a in 0..9) { bla bla bla } [/code] Este <strong>0..9</strong> consiste em uma escala, que implementa a interface Collection do Java. Sendo assim, é mais do que sintaxe: é um objeto por si só. Declarar uma escala é bastante simples. Basta usar a sintaxe abaixo: [limite inferior]..[limite superior] ".." consiste em um operador de precedência baixa, sendo assim é uma boa idéia sempre definir seus intervalos dentro de parênteses, tal como (0..9). Se quiser, há também um outro operador que você pode usar ao definir escalas. O operador "..<". Neste caso, estamos dizendo que o valor da direita não entra entre os valores da escala. O código em Java exposto no primeiro exemplo poderia portanto ser reescrito como [code language='java'] for (a in 0..<10) { bla bla bla } [/code] Como mencionei, intervalos são objetos. Sendo assim, há alguns métodos e funções que você pode chamar, tal como no exemplo abaixo: [code language='java'] (0..10).contains(4) // Verifica se o intervalo contém o valor 4 (0..10).each {elemento -> print elemento} // each executa uma closure (leia o tópico sobre closures para maiores detalhes)
Escalas só aceitam números? Não. Basicamente, aceitam qualquer tipo de objeto pode ser usado desde que as duas condições abaixo sejam satisfeitas:
- O tipo implementa próximo e anterior, ou seja, faz override dos operadores ++ e — (mais sobre sobrescrita de operadores aqui)
(Groovy sobrescreve os operadores ++ e — em java.util.Date e alguns outros tipos básicos para você) - O tipo implementa a interface java.lang.Comparable
Listas
Uma lista é declarada em Groovy usando a seguinte sintaxe:
[ (uma série de objetos separdos por vígula) ].
Exemplo:
lista = ["uma", "lista", "de", "strings"] /* Claro, você terá acesso também a todos os métodos da interface java.util.List */ lista.contains("uma") lista.add("coisas da vida") print "A lista possui ${lista.size()} itens!"
E ainda há alguns operadores bem interessantes para se lidar com listas, tal como no exemplo abaixo:
lista = [] // Como incluir um novo item na lista? lista += "primeiro item" // Como incluir mais de um item? lista += ["segundo", "terceiro", "quarto"] // E como eu removo um item? lista -= ["terceiro"]
Resumindo: seu código ficará beeem mais fácil de ser compreendido.
Mapas (hashes)
Mapas em Groovy também estão embutidos direto na sintaxe da linguagem, tal como pode ser visto abaixo:
def mapa = ["a":1, "b":2, "c":3] // Definição do mapa /* A sintaxe é simples: dentro dos colchetes, o elemento a esquerda do caractere ":" representa o índice, e o valor à direita, o valor */ // Claro, todos os métodos da interface java.util.Map podem ser chamados aqui, tal como println "Eis que nosso mapa possui ${mapa.size()}" println "E o valor de c é... ${mapa.get("e")}"
Aliás, em Groovy, você pode passar mapas para construtores de classes também, já as populando, tal como no exemplo abaixo:
class Pessoa { String nome String descricao } Pessoa pessoa = new Pessoa(nome:"Seu nome", descricao:"Um cara ai") /* O que Groovy faz aqui: ele recebe um hashmap, percorre suas chaves, as compara com os atributos da classe e os preenche. Prático não acha? Em apenas uma linha você economiza n! */
Deixe uma resposta