O Gradle utiliza scripts baseados na linguagem Groovy, uma ferramenta poderosa no ecossistema JVM. Para dominar o Gradle, é crucial compreender os fundamentos do Groovy.
Características do Groovy
- Groovy é uma linguagem DSL (Domain-Specific Language), otimizada para contextos específicos como automação de builds.
- Roda na Máquina Virtual Java (JVM), compilada para bytecode, garantindo portabilidade e integração com bibliotecas Java.
- Incorpora funcionalidades de linguagens como Python e Ruby, facilitando a escrita de scripts expressivos.
- Suporta tipagem dinâmica, closures e programação orientada a objetos e procedimentos.
Definições e Tipos de Variáveis
Em Groovy, as variáveis podem ser definidas de duas formas principais:
- Tipagem Forte: Especifica o tipo explicitamente, como
int contador = 10. - Tipagem Fraca: Usa a palavra-chave
def, permitindo que o compilador infira o tipo automaticamente, por exemplo,def valor = 5.
Note que todos os tipos primitivos são automaticamente encapsulados em seus equivalentes de objeto (por exemplo, int torna-se Integer). O ponto e vírgula é opcional, e funções como println podem ser chamadas sem parênteses.
Exemplo de Variáveis
// Definição com tipagem forte
int xValor = 10
println xValor.class
double yValor = 3.14
println yValor.class
// Definição com tipagem fraca
def aVariavel = 10
println aVariavel.class
def bVariavel = 3.14
println bVariavel.class
def nome = "Groovy"
println nome.class
// Saída esperada: classes como Integer, Double, BigDecimal, String
Manipulação de Strings
Groovy oferece múltiplas formas de definir strings, incluindo a classe GString para interpolação.
Tipos de Strings
- Aspas Simples: Strings imutáveis, como
def mensagem = 'Olá, mundo'. - Aspas Triplas: Preservam formatação, útil para múltiplas linhas.
- Aspas Duplas: Permitem interpolação com
$, resultando em objetosGString.
Exemplo de GString
def linguagem = "Groovy"
def saudacao = "Bem-vindo ao $linguagem"
println saudacao
println saudacao.class // Saída: org.codehaus.groovy.runtime.GStringImpl
// Interpolação com expressões
def calculo = "Resultado: ${5 * 3}"
println calculo // Saída: Resultado: 15
Strings do tipo GString e String são intercambiáveis em métodos, simplificando o desenvolvimento.
Métodos Comuns de String
def frase = 'automação de build'
println frase.reverse() // Inverte a string
println frase.capitalize() // Primeira letra maiúscula
// Operações com índices e intervalos
println frase[0..4] // Extrai substring
println frase - 'build' // Remove substring
// Verificações
def numStr = '123'
println numStr.isNumber() // Saída: true
Controle Lógico
Estruturas de controle como if/else e while são semelhantes ao Java, mas switch/case e for possuem extensões.
Exemplo de Switch Expandido
def entrada = 3.14
def resultado
switch (entrada) {
case 'texto':
resultado = 'string'
break
case [1, 2, 3]:
resultado = 'lista'
break
case 1..5:
resultado = 'intervalo'
break
case BigDecimal:
resultado = 'BigDecimal'
break
default:
resultado = 'padrão'
break
}
println resultado // Saída: BigDecimal
Loops com Coleções
// Loop com intervalo
def soma = 0
for (i in 0..4) {
soma += i
}
println soma // Saída: 10
// Loop com mapa
def notas = ['Ana':85, 'João':90, 'Maria':78]
for (entry in notas) {
println "${entry.key}: ${entry.value}"
}
Closures em Groovy
Colsures são blocos de código reutilizáveis, semelhantes a lambdas. Podem ter parâmetros e valores de retorno.
Conceitos Básicos
// Definição e chamada de closure
def saudacao = { println "Olá, Groovy!" }
saudacao() // Chama a closure
// Closure com parâmetros
def saudacaoNome = { nome -> println "Olá, $nome!" }
saudacaoNome('Mundo')
// Parâmetro implícito 'it'
def saudacaoPadrao = { println "Olá, $it!" }
saudacaoPadrao('Gradle')
Uso com Métodos
// Exemplo com método upto para fatorial
int calcularFatorial(int num) {
int resultado = 1
1.upto(num) { i -> resultado *= i }
return resultado
}
println calcularFatorial(5) // Saída: 120
// Exemplo com times para soma
int somarAte(int limite) {
int total = 0
limite.times { i -> total += i }
return total
}
println somarAte(10) // Saída: 45
Closures com Strings
def texto = 'groovy e gradle'
// Método each para iteração
texto.each { caractere -> print "$caractere " }
println()
// Método find para busca
def primeiroNumero = 'abc123def'.find { it.isNumber() }
println primeiroNumero // Saída: 1
Delegação e Estratégias de Closure
Closures possuem referências como this, owner e delegate, que definem o escopo de resolução.
class Configuracao {
String nome = 'Padrão'
}
def minhaClosure = {
println "Nome: $nome"
}
def config = new Configuracao(nome: 'Customizado')
minhaClosure.delegate = config
minhaClosure.resolveStrategy = Closure.DELEGATE_FIRST
minhaClosure() // Saída: Nome: Customizado
Estruturas de Dados
Listas
// Criação de listas
def numeros = [10, 20, 30, 40]
println numeros.class // java.util.ArrayList
// Ordenação personalizada
def valores = [-3, 5, -1, 8]
valores.sort { a, b -> Math.abs(a) <=> Math.abs(b) }
println valores // Saída: [-1, -3, 5, 8]
// Busca e filtragem
def positivos = numeros.findAll { it > 15 }
println positivos // Saída: [20, 30, 40]
Mapas
// Definição de mapa
def cidades = ['SP': 'São Paulo', 'RJ': 'Rio de Janeiro']
println cidades['SP']
// Adição e iteração
cidades['MG'] = 'Minas Gerais'
cidades.each { chave, valor -> println "$chave: $valor" }
// Consultas
def capitais = cidades.findAll { it.value.contains('Rio') }
println capitais
Intervalos
def intervalo = 1..10
println intervalo.from // 1
println intervalo.to // 10
println intervalo.contains(5) // true
Programação Orientada a Objetos
Classes em Groovy têm métodos e atributos públicos por padrão, com getters/setters gerados automaticamente.
class Projeto {
String nome
int versao
void incrementarVersao() {
versao++
}
}
def meuProjeto = new Projeto(nome: 'App', versao: 1)
meuProjeto.incrementarVersao()
println meuProjeto // Saída: Projeto(nome: App, versao: 2)
Metaprogramação
Groovy permite modificação dinâmica de classes em tempo de execução via MetaClass.
// Adicionando método dinamicamente
String.metaClass.reverter = { -> delegate.reverse() }
def texto = 'groovy'
println texto.reverter() // Saída: yvoorg
// Adicionando propriedade
Integer.metaClass.ehPar = { -> delegate % 2 == 0 }
println 4.ehPar() // Saída: true
Mecanismos como methodMissing e invokeMethod permitem tratamento flexível de chamadas de métodos inexistentes.