Baixar o código: learngroovy.groovy
Groovy - Uma linguagem dinâmica para a plataforma Java. Leia mais aqui.
/*
Prepare-se:
1) Instale a máquina virtual de Groovy - http://gvmtool.net/
2) Instale o Groovy: gvm install groovy
3) Inicie o console groovy digitando: groovyConsole
*/
// Comentário de uma linha inicia-se com duas barras
/*
Comentário de múltiplas linhas são assim.
*/
// Olá Mundo!
println "Olá mundo!"
/*
Variáveis:
Você pode atribuir valores a variáveis para uso posterior
*/
def x = 1
println x
x = new java.util.Date()
println x
x = -3.1499392
println x
x = false
println x
x = "Groovy!"
println x
/*
Coleções e mapeamentos
*/
//Criando uma lista vazia
def tecnologias = []
/*** Adicionando elementos à lista ***/
// Assim como Java
tecnologias.add("Grails")
// Shift para esquerda adiciona e retorna a lista
tecnologias << "Groovy"
// Adição de múltiplos elementos
tecnologias.addAll(["Gradle","Griffon"])
/*** Removendo elementos da lista ***/
// Assim como Java
tecnologias.remove("Griffon")
// Subtração também funciona
tecnologias = technologies - 'Grails'
/*** Iterando sobre listas ***/
// Itera sobre os elementos da lista
tecnologias.each { println "Tecnologias: $it"}
tecnologias.eachWithIndex { it, i -> println "$i: $it"}
/*** Checando os elementos da lista ***/
//Avalia se a lista contém o elemento 'Groovy'
contem = tecnologias.contains( 'Groovy' )
// Ou
contem = 'Groovy' in tecnologias
// Checagem por múltiplos elementos
tecnologias.containsAll(['Groovy','Grails'])
/*** Ordenando listas ***/
// Ordena a lista (altera a lista in-place)
tecnologias.sort()
// Para ordenar a lista sem alterar a original
tecnologiasOrdenadas = tecnologias.sort( false )
/*** Manipulando listas ***/
//Substitui todos os elementos da lista
Collections.replaceAll(tecnologias, 'Gradle', 'gradle')
//Desorganiza a lista
Collections.shuffle(tecnologias, new Random())
//Limpa a lista
technologies.clear()
//Criando um mapeamento vazio
def devMap = [:]
//Adicionando valores
devMap = ['nome':'Roberto', 'framework':'Grails', 'linguagem':'Groovy']
devMap.put('ultimoNome','Perez')
//Iterando sobre os elementos do mapeamento
devMap.each { println "$it.key: $it.value" }
devMap.eachWithIndex { it, i -> println "$i: $it"}
//Avalia se um mapeamento contém uma chave
assert devMap.containsKey('nome')
//Avalia se um mapeamento contém um valor
assert devMap.containsValue('Roberto')
//Pega as chaves de um mapeamento
println devMap.keySet()
//Pega os valores de um mapeamento
println devMap.values()
/*
Groovy Beans
GroovyBeans são JavaBeans com uma sintaxe muito mais simples.
Quando Groovy é compilado para bytecode, as seguintes regras são usadas:
* Se o nome é declarado com um modificador de acesso(public, private or
protected) então um atributo é gerado.
* Um nome declarado sem modificador de acesso gera um campo privado com
getter e setter públicos (ou seja, uma propriedade).
* Se uma propriedade é declarada como final, um campo private final é criado
e o setter não é gerado.
* Você pode declarar uma propriedade e também declarar seus próprios getters
e setters.
* Você pode declarar uma propriedade e um campo com o mesmo nome, a propriedade
usará este campo.
* Se você quer uma propriedade private ou protected, você deve prover seus
próprios getters e setters, que devem ser declarados como private ou protected.
* Se você acessar uma propriedade dentro da classe e esta propriedade é definida
em tempo de compilação com 'this', implícito ou explícito (por exemplo,
this.foo, ou simplesmente foo), Groovy acessará este campo diretamente, sem
passar pelo getter ou setter.
* Se você acessar uma propriedade que não existe usando foo, explicitamente ou
implicitamente, então Groovy irá acessar esta propriedade através da meta
classe, o que pode falhar em tempo de execução.
*/
class Foo {
// propriedade de leitura, apenas
final String nome = "Roberto"
// propriedade de leitura, apenas, com getter e setter públicos
String linguagem
protected void setLinguagem(String linguagem) { this.linguagem = linguagem }
// propriedade tipada dinamicamente
def ultimoNome
}
/*
Condicionais e loops
*/
//Groovy suporta a sintaxe if-else
def x = 3
if(x==1) {
println "Um"
} else if(x==2) {
println "Dois"
} else {
println "X é maior que Dois"
}
//Groovy também suporta o operador ternário
def y = 10
def x = (y > 1) ? "funcionou" : "falhou"
assert x == "funcionou"
//E suporta o 'The Elvis Operator' também!
//Em vez de usar o operador ternário:
displayName = nome.name ? nome.name : 'Anonimo'
//Podemos escrever:
displayName = nome.name ?: 'Anonimo'
//Loop 'for'
//Itera sobre um intervalo (range)
def x = 0
for (i in 0 .. 30) {
x += i
}
//Itera sobre uma lista
x = 0
for( i in [5,3,2,1] ) {
x += i
}
//Itera sobre um array
array = (0..20).toArray()
x = 0
for (i in array) {
x += i
}
//Itera sobre um mapa
def map = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy']
x = ""
for ( e in map ) {
x += e.value
x += " "
}
assert x.equals("Roberto Grails Groovy ")
/*
Operadores
Sobrecarga de Operadores para uma lista dos operadores comuns que
Grooby suporta:
http://www.groovy-lang.org/operators.html#Operator-Overloading
Operadores Groovy úteis
*/
//Operador de espalhamento: invoca uma ação sobre todos os itens de um
//objeto agregador.
def tecnologias = ['Groovy','Grails','Gradle']
tecnologias*.toUpperCase() // = to tecnologias.collect { it?.toUpperCase() }
//Operador de navegação segura: usado para evitar NullPointerException.
def usuario = User.get(1)
def nomeUsuario = usuario?.nomeUsuario
/*
Closures
Um closure, em Groovy, é como um "bloco de código" ou um ponteiro para método.
É um pedação de código que é definido e executado em um momento posterior.
Mais informação em: http://www.groovy-lang.org/closures.html
*/
//Exemplo:
def clos = { println "Hello World!" }
println "Executando o closure:"
clos()
//Passando parêmetros para um closure
def soma = { a, b -> println a+b }
soma(2,4)
//Closures podem referir-se a variáveis que não estão listadas em sua
//lista de parêmetros.
def x = 5
def multiplicarPor = { num -> num * x }
println multiplicarPor(10)
// Se você tiver um closure que tem apenas um argumento, você pode omitir
// o parâmetro na definição do closure
def clos = { print it }
clos( "oi" )
/*
Groovy pode memorizar resultados de closures
*/
def cl = {a, b ->
sleep(3000) // simula processamento
a + b
}
mem = cl.memoize()
def chamaClosure(a, b) {
def inicio = System.currentTimeMillis()
mem(a, b)
println "Os inputs(a = $a, b = $b) - tomam ${System.currentTimeMillis() - inicio} msecs."
}
chamaClosure(1, 2)
chamaClosure(1, 2)
chamaClosure(2, 3)
chamaClosure(2, 3)
chamaClosure(3, 4)
chamaClosure(3, 4)
chamaClosure(1, 2)
chamaClosure(2, 3)
chamaClosure(3, 4)
/*
Expando
A classe Expando é um bean dinâmico que permite adicionar propriedades e
closures como métodos a uma instância desta classe
http://mrhaki.blogspot.mx/2009/10/groovy-goodness-expando-as-dynamic-bean.html
*/
def usuario = new Expando(nome:"Roberto")
assert 'Roberto' == nome.name
nome.lastName = 'Pérez'
assert 'Pérez' == nome.lastName
nome.showInfo = { out ->
out << "Name: $name"
out << ", Last name: $lastName"
}
def sw = new StringWriter()
println nome.showInfo(sw)
/*
Metaprogramação (MOP)
*/
//Usando a ExpandoMetaClasse para adicionar comportamento
String.metaClass.testAdd = {
println "adicionamos isto"
}
String x = "teste"
x?.testAdd()
//Interceptando chamadas a métodos
class Test implements GroovyInterceptable {
def soma(Integer x, Integer y) { x + y }
def invocaMetodo(String name, args) {
System.out.println "Invoca método $name com argumentos: $args"
}
}
def teste = new Test()
teste?.soma(2,3)
teste?.multiplica(2,3)
//Groovy suporta propertyMissing para lidar com tentativas de resolução de
//propriedades.
class Foo {
def propertyMissing(String nome) { nome }
}
def f = new Foo()
assertEquals "boo", f.boo
/*
TypeChecked e CompileStatic
Groovy, por natureza, é e sempre será uma linguagem dinâmica, mas ela também
suporta typecheked e compilestatic
Mais informações: http://www.infoq.com/articles/new-groovy-20
*/
//TypeChecked
import groovy.transform.TypeChecked
void testeMethod() {}
@TypeChecked
void test() {
testeMethod()
def nome = "Roberto"
println noomee
}
//Outro exemplo:
import groovy.transform.TypeChecked
@TypeChecked
Integer test() {
Integer num = "1"
Integer[] numeros = [1,2,3,4]
Date dia = numeros[1]
return "Teste"
}
//Exemplo de CompileStatic :
import groovy.transform.CompileStatic
@CompileStatic
int soma(int x, int y) {
x + y
}
assert soma(2,5) == 7
Junte-se a um grupo de usuários Groovy
Sugestões ou correções? Abra uma issue no repositório do GitHub, ou faça um pull request você mesmo!
Originalmente contribuído por Roberto Pérez Alcolea e atualizado por 9 colaboradores.