O documento apresenta os principais recursos da linguagem Groovy e do framework Grails, destacando como o código fica mais conciso graças ao uso do dialeto Groovy e da convenção sobre configuração. Também descreve recursos como closures, operadores como ?. e ?:, e como a reflexão torna o acesso a propriedades e métodos mais simples.
3. Groovy + Spring + Hibernate + "Convention
over configuration" + ...
Esta apresentação é mais focada na diferença do código-fonte, mas saiba que
Grails juntou muito bem frameworks bastante utilizados pela comunidade Java
(especialmente Spring e Hibernate).
Graças ao dialeto Groovy e à prática de "convenção sobre configuração" o
resultado é um código-fonte bem mais conciso.
Vamos ao que interessa...
5. Mapas são LinkedHashMap
...ao invés de java.util.HashMap para assim
manter a ordem dos elementos.
def map = [red:1, blue:2]
Se precisar de outro tipo de mapa é só
instanciar como é feito no Java.
6. Getters e setters
Basta acessar a propriedade diretamente. Ex.:
cliente.nome
O getter vai ser invocado quando estiver lendo
o valor e o setter quando estiver atribuindo um
novo valor.
7. Getters e setters
Não é necessário (mas é permitido e serão
chamados se existirem) implementar métodos
getters e setters. Ex.:
void setNome(String nome) {
this.nome = nome.trim();
}
9. Closure
Pedaço de código que pode ser atribuído a uma
variável. Pode ser passado como parâmetro e
invocado dentro de métodos.
Lembra uma classe anônima porém sem
precisar implementar uma Interface. Nota: eles
podem acessar variáveis não "final" fora de seu
escopo.
11. Closure
É um jeito prático de implementar interfaces
sem precisar definir todos os métodos (útil em
testes por exemplo):
def conn = [
close: { -> println "closed},
setAutoCommit: { boolean autoCommit -> println "autoCommit:
$autoCommit" }
] as java.sql.Connection
16. Comparando objetos
O sinal "==" funciona diferente do Java pois ele
compara os valores.
Para saber se ambas as referências apontam
para o mesmo objeto, utilizar:
foo.is(bar)
17. Invocação de método de acordo com
tipo to parâmetro
void close(Connection c) {
…
}
void close(Object o) {
...
}
18. Invocação de método de acordo com
tipo to parâmetro
No Java este código invocaria close(Object):
Object connection = createConnection();
close(connection);
No groovy seria chamado o close(Connection)
porque seria resolvido em Runtime.
19. Groovy Strings
Multilinhas (com três aspas):
def name = "Carl Sagan"
def texto = """
Caro $name,
Não esqueça de alimentar os gatinhos."""
20. 'this' funciona para acesso estático
ex.:
private static final Logger LOG = Logger.getLogger(this)
24. Operadores: ?.
Acesso null-safe (se "person" for null o valor
atribuído será null ao invés de dar
NullPointerException):
String name = person?.name
25. Operadores: ?:
?: é operador "Elvis" que encurta ternários. Você já fez algo
assim em Java?
Integer qtd = qtdParam ? qtdParam : 10
Com grails você pode fazer assim:
Integer qtd = qtdParam ?: 10
26. Operadores: *.
*. é o "spread". Se você quer todos os nomes de
clientes de um array você pode fazer assim:
String[] nomes = clientes*.nome
27. Operadores: .@
Como já vimos, ao acessar "cliente.nome" o método
getNome (ou setNome se for atribuição) é chamado
automaticamente.
Se desejar evitar por exemplo o getNome e acessar
diretamente a propriedade, utilize o operador .@. Ex.:
cliente.@nome
28. Operadores: as
Facilita escolha do tipo de estrutura de dados. Por ex. criar
um Set ao invés de um List:
def things = ['a', 'b', 'b', 'c'] as Set
assert things.getClass().simpleName == 'HashSet'
assert things.size() == 3
30. Operadores: .&
Permite tratar um método como um closure
(podendo assim passar a referência do método
como parâmetro). Ex.:
def add = new MathUtils().&add
add(x, y)
32. Groovy "demais"...
def foo = bar(5, true) // o que é "foo"??
def fazAlgo() {...} // O que fazAlgo retorna? É void? Por que
não declará-lo como void?
def fazAlgo = {} // Definir métodos como closure ao invés
da declaração normal pode fazê-lo ficar de fora de
interceptações como por exemplo quando o Spring está
marcando os métodos como transacionais.
33. Linguagem dinâmica permite mais
bugs...
int hc = someObject.hashcode()
Se o método na verdade se chama hashCode só saberemos
na hora que o código for executado, não quando for
compilado. Testes deveriam nos prevenir destes casos.
As anotações @TypeChecked e @CompileStatic ajudam
nestes casos e melhoram desempenho do código porém há
perda de flexibilidade (por ex. metaprogramming).