Les traits cachés de Groovy?

il semble que Groovy a été oublié dans ce fil donc je vais juste poser la même question pour Groovy.

  • Essayer de limiter les réponses à Groovy de base
  • une caractéristique par réponse
  • donner un exemple et une brève description de la fonctionnalité, pas seulement un lien vers la documentation
  • étiqueter la caractéristique en utilisant le titre en caractères gras comme première ligne

voir aussi:

  1. "1519160920 des fonctionnalités Cachées de Python
  2. "1519200920 des fonctionnalités Cachées de Ruby
  3. "1519240920 des fonctionnalités Cachées de Perl
  4. "1519280920 des fonctionnalités Cachées de Java
78
demandé sur 10 revs, 7 users 37%anon 2008-11-20 00:53:57

30 réponses

utilisant l'opérateur à points étalés

def animals = ['ant', 'buffalo', 'canary', 'dog']
assert animals.size() == 4
assert animals*.size() == [3, 7, 6, 3]

C'est un raccourci pour animals.collect { it.size() } .

56
répondu 2 revs, 2 users 92%Paul King 2014-05-23 21:21:44

la méthode avec permet de tourner ceci:

 myObj1.setValue(10)
 otherObj.setTitle(myObj1.getName())
 myObj1.setMode(Obj1.MODE_NORMAL)

dans ce

 myObj1.with {
    value = 10
    otherObj.title = name
    mode = MODE_NORMAL
 }
39
répondu Rui Vieira 2014-04-30 08:52:17

utilisant des hachures comme pseudo-objets.

def x = [foo:1, bar:{-> println "Hello, world!"}]
x.foo
x.bar()

combiné avec duck typing, vous pouvez aller un long chemin avec cette approche. N'avez même pas besoin de sortir le "comme" de l'opérateur.

37
répondu Robert Fischer 2008-11-19 22:07:37

Quelqu'un sait pour Elvis ?

def d = "hello";
def obj = null;

def obj2 = obj ?: d;   // sets obj2 to default
obj = "world"

def obj3 = obj ?: d;  // sets obj3 to obj (since it's non-null)
37
répondu Bill James 2015-07-22 08:52:56

trouver quelles méthodes sont sur un objet est aussi facile que de demander à la métaclasse:

"foo".metaClass.methods.name.sort().unique()

imprime:

["charAt", "codePointAt", "codePointBefore", "codePointCount", "compareTo",
 "compareToIgnoreCase", "concat", "contains", "contentEquals", "copyValueOf", 
 "endsWith", "equals", "equalsIgnoreCase", "format", "getBytes", "getChars", 
 "getClass", "hashCode", "indexOf", "intern", "lastIndexOf", "length", "matches", 
 "notify", "notifyAll", "offsetByCodePoints", "regionMatches", "replace", 
 "replaceAll", "replaceFirst", "split", "startsWith", "subSequence", "substring", 
 "toCharArray", "toLowerCase", "toString", "toUpperCase", "trim", "valueOf", "wait"]
35
répondu Ted Naleid 2009-06-15 17:20:56

pour intercepter les méthodes statiques manquantes, utilisez la

 Foo {
    static A() { println "I'm A"}

     static $static_methodMissing(String name, args) {
        println "Missing static $name"
     }
 }

Foo.A()  //prints "I'm A"
Foo.B()  //prints "Missing static B"

- Ken

28
répondu ken 2014-04-05 18:02:35

destruction

il pourrait être appelé quelque chose d'autre dans Groovy; il est appelé la déstructuration dans clojure. Tu ne croiras jamais à quel point ça peut être pratique.

def list = [1, 'bla', false]
def (num, str, bool) = list
assert num == 1
assert str == 'bla'
assert !bool
24
répondu Bojan Dolinar 2012-10-04 14:10:03

Pour les tests de code java avec groovy, le graphe d'objet builder est étonnante:

def company = builder.company( name: 'ACME' ) {
   address( id: 'a1', line1: '123 Groovy Rd', zip: 12345, state: 'JV' )
   employee(  name: 'Duke', employeeId: 1 ){
      address( refId: 'a1' )
   }
}

caractéristique Standard, mais toujours très agréable.

ObjectGraphBuilder

(vous avez besoin de donner n'importe quelles propriétés de votre POJO qui sont List s une valeur par défaut d'une liste vide plutôt que null pour le soutien de constructeur à travailler.)

21
répondu krosenvold 2015-03-26 15:25:30
println 
"""
Groovy has "multi-line" strings.
Hooray!
"""
19
répondu Brian 2012-08-27 22:19:26

En groovy, 1.6, les expressions régulières de travail avec l'ensemble de la fermeture des itérateurs (comme chaque, de recueillir, d'injecter, etc) et vous permettent de travailler facilement avec les groupes de capture:

def filePaths = """
/tmp/file.txt
/usr/bin/dummy.txt
"""

assert (filePaths =~ /(.*)\/(.*)/).collect { full, path, file -> 
        "$file -> $path"
    } ==  ["file.txt -> /tmp", "dummy.txt -> /usr/bin"]
15
répondu Ted Naleid 2008-11-21 06:25:35

contrairement à Java, dans Groovy, tout peut être utilisé dans une instruction switch , pas seulement les types primitifs. Dans une "méthode" type eventPerformed 151960920"

switch(event.source) {
   case object1:
        // do something
        break
   case object2:
        // do something
        break
}
15
répondu Rui Vieira 2008-11-21 10:11:20

utilisant L'opérateur du vaisseau spatial

j'aime Vaisseau spatial "d'opérateur de 151970920" , utile pour toutes sortes de tri personnalisée scénarios. Quelques exemples d'utilisation sont ici . Une situation dans laquelle il est particulièrement utile est dans la création d'un comparateur à la volée d'un objet en utilisant plusieurs champs. par exemple

def list = [
    [ id:0, first: 'Michael', last: 'Smith', age: 23 ],
    [ id:1, first: 'John', last: 'Smith', age: 30 ],
    [ id:2, first: 'Michael', last: 'Smith', age: 15 ],    
    [ id:3, first: 'Michael', last: 'Jones', age: 15 ],   
]

// sort list by last name, then first name, then by descending age
assert (list.sort { a,b -> a.last <=> b.last ?: a.first <=> b.first ?: b.age <=> a.age })*.id == [ 3,1,0,2 ]
15
répondu mmigdol 2011-08-09 17:19:09

les fermetures peuvent faire disparaître tous les vieux jeux de gestion des ressources. Le flux de fichiers est automatiquement fermé à la fin du bloc:

new File("/etc/profile").withReader { r ->
    System.out << r
}
14
répondu John Flinchbaugh 2008-11-20 18:56:02

les caractéristiques fournies par les transformations à l'intérieur du paquet groovy.transform de GDK, telles que:

  • @Immutable : L'annotation @Immutable demande au compilateur d'exécuter une transformation AST qui ajoute les getters nécessaires, les constructeurs, les égaux, le hashCode et d'autres méthodes d'aide qui sont typiquement écrites lors de la création de classes immuables avec les propriétés définies.
  • @CompileStatic : cela permettra au compilateur Groovy d'utiliser des vérifications de temps de compilation dans le style de Java puis d'effectuer une compilation statique, contournant ainsi le protocole d'objet meta De Groovy.
  • @Canonical : L'annotation @Canonical demande au compilateur d'exécuter une transformation AST qui ajoute des constructeurs de positions, des égaux, du hashCode et une jolie impression toString à votre classe.

autres:

  • @Slf4j cette transformation locale ajoute une capacité de journalisation à votre programme en utilisant la journalisation LogBack. Chaque appel de méthode sur une variable non liée nommée log sera mappé à un appel à l'enregistreur.
  • Groovy XML de Slurper : facile à parser XML. Killer feature!
13
répondu Hans Westerbeek 2013-06-28 17:38:42

vous pouvez convertir une liste en une carte en utilisant toSpreadMap(), pratique lorsque l'ordre dans la liste est suffisant pour déterminer les clés et les valeurs associées. Voir l'exemple ci-dessous.

def list = ['key', 'value', 'foo', 'bar'] as Object[]
def map = list.toSpreadMap()

assert 2 == map.size()
assert 'value' == map.key
assert 'bar' == map['foo']
12
répondu ken 2010-09-17 21:32:46

Fermeture De La Base De L'Implémentation De L'Interface

si vous avez une référence dactylographiée telle que:

MyInterface foo

vous pouvez implémenter l'interface entière en utilisant:

foo = {Object[] args -> println "This closure will be called by ALL methods"} as MyInterface

alternativement, si vous voulez implémenter chaque méthode séparément, vous pouvez utiliser:

foo = [bar: {-> println "bar invoked"}, 
    baz: {param1 -> println "baz invoked with param $param1"}] as MyInterface
12
répondu Don 2013-01-07 08:52:38

Supprimer null valeurs de la liste

def list = [obj1, obj2, null, obj4, null, obj6]
list -= null
assert list == [obj1, obj2, obj4, obj6]
8
répondu BIdesi 2014-01-16 12:05:34

je sais que je suis un peu en retard, mais je pense qu'il y a de belles choses qui manquent ici:

Collection Plus / Moins opérateurs

def l = [1, 2, 3] + [4, 5, 6] - [2, 5] - 3 + (7..9)
assert l == [1, 4, 6, 7, 8, 9]

def m = [a: 1, b: 2] + [c: 3] - [a: 1]
assert m == [b: 2, c: 3]

Switch

switch (42) {
  case 0: .. break
  case 1..9: .. break
  case Float: .. break
  case { it % 4 == 0 }: .. break
  case ~/\d+/: .. break
}

fourchettes et indexation

assert (1..10).step(2) == [1, 3, 5, 7, 9]
assert (1..10)[1, 4..8] == [2, 5, 6, 7, 8, 9]
assert ('a'..'g')[-4..-2] == ['d', 'e', 'f']

Unicode variables names

def α = 123
def β = 456
def Ω = α * β
assert Ω == 56088
7
répondu micha 2014-01-15 20:03:13

@Délégué

class Foo {
    def footest() { return "footest"}   
}

class Bar {
    @Delegate Foo foo = new Foo()     
}

def bar = new Bar()

assert "footest" == bar.footest()
7
répondu Omnipresent 2015-03-26 15:29:36

trait de Soulignement dans les littéraux

quand on écrit de longs nombres littéraux, il est plus difficile de comprendre comment certains nombres sont regroupés, par exemple avec des groupes de milliers, de mots, etc. En vous permettant de placer des underscore dans les nombres littéraux, il est plus facile de repérer ces groupes:

long creditCardNumber = 1234_5678_9012_3456L
long socialSecurityNumbers = 999_99_9999L
double monetaryAmount = 12_345_132.12
long hexBytes = 0xFF_EC_DE_5E
long hexWords = 0xFFEC_DE5E
long maxLong = 0x7fff_ffff_ffff_ffffL
long alsoMaxLong = 9_223_372_036_854_775_807L
long bytes = 0b11010010_01101001_10010100_10010010
6
répondu Pankaj Shinde 2015-04-13 12:23:49

Argument réorganiser avec des arguments implicites est un autre nice.

ce code:

def foo(Map m=[:], String msg, int val, Closure c={}) {
  [...]
}

crée toutes ces différentes méthodes:

foo("msg", 2, x:1, y:2)
foo(x:1, y:2, "blah", 2)
foo("blah", x:1, 2, y:2) { [...] }
foo("blah", 2) { [...] }

et plus. Il est impossible de foirer en mettant les arguments nommés et ordinaux dans le mauvais ordre/position.

bien sûr, dans la définition de "foo", vous pouvez laisser "String" et "int" de "String msg" et "int val" -- je les ai laissés dans juste pour plus de clarté.

5
répondu Robert Fischer 2008-11-19 22:53:47

je pense que c'est une combinaison de fermetures comme paramètre et paramètre-valeurs par défaut:

public void buyItems(Collection list, Closure except={it > 0}){
  list.findAll(){except(it)}.each(){print it}
}
buyItems([1,2,3]){it > 2}
buyItems([0,1,2])

gravures: "312

4
répondu Peter Rader 2011-10-25 16:17:27

utilisant l'opérateur de propagation dans les paramètres de la méthode

ceci est une grande aide lors de la conversion de code EN données:

def exec(operand1,operand2,Closure op) {
    op.call(operand1,operand2)
}

def addition = {a,b->a+b}
def multiplication = {a,b->a*b}

def instructions = [
     [1,2,addition],
     [2,2,multiplication]
]

instructions.each{instr->
    println exec(*instr)
}

cet usage est également utile:

String locale="en_GB"

//this invokes new Locale('en','GB')
def enGB=new Locale(*locale.split('_'))
4
répondu loteq 2013-03-08 13:57:26

Memoization

Memoization est une technique d'optimisation qui consiste à stocker les résultats d'appels de fonction coûteux et de retourner le résultat caché chaque fois que la fonction est appelée à nouveau avec les mêmes arguments.

il y a une version illimitée, qui cache toujours une paire de (arguments d'entrée, valeur de retour) qu'elle ne verra jamais; et une version limitée, qui cache les N derniers arguments d'entrée Vus et leurs résultats, en utilisant un cache LRU.

Memoization de méthodes:

import groovy.transform.Memoized

@Memoized
Number factorial(Number n) {
    n == 0 ? 1 : factorial(n - 1)
}

@Memoized(maxCacheSize=1000)
Map fooDetails(Foo foo) {
    // call expensive service here
}

Memoization de fermetures:

def factorial = {Number n ->
    n == 0 ? 1 : factorial(n - 1)
}.memoize()

fooDetails = {Foo foo ->
    // call expensive service here
}.memoizeAtMost(1000)

la page Wikipedia contient de nombreuses informations sur les utilisations de la Mémoisation en informatique. Je me contenterai de souligner une simple utilisation pratique.

reporter l'initialisation d'une constante au dernier moment possible

parfois vous avez une valeur constante qui ne peut pas être initialisée à la définition de classe ou au temps de création. Par exemple, l'expression constante peut faire usage d'une autre constante ou une méthode d'une classe différente, qui sera branché par quelque chose d'autre (ou de Printemps) après l'initialisation de votre classe.

dans ce cas, vous pouvez convertir votre constante en getter et la décorer avec @Memoized . Il ne sera calculé une fois, la première fois c'est accessible, puis la valeur mise en cache et réutilisée:

import groovy.transform.Memoized

@Memoized
def getMY_CONSTANT() {
    // compute the constant value using any external services needed
}
3
répondu Tobia 2015-05-06 10:32:09

Groovy peut fonctionner comme Javascript. Vous pouvez avoir des vars privés et des fonctions via la fermeture. Vous pouvez également curry fonctions avec des fermetures.

class FunctionTests {

def privateAccessWithClosure = {

    def privVar = 'foo'

    def privateFunc = { x -> println "${privVar} ${x}"}

    return {x -> privateFunc(x) } 
}


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

def curryAdd = { x ->
    return { y-> addTogether(x,y)}
}

public static void main(String[] args) {
    def test = new FunctionTests()

    test.privateAccessWithClosure()('bar')

    def curried = test.curryAdd(5)

    println curried(5)
}
}

sortie:

foo bar 10

2
répondu Jason 2012-11-20 09:34:54

Dynamic invocation de méthode

vous pouvez invoquer une méthode en utilisant une chaîne de caractères Avec son nom

class Dynamic {
    def one() { println "method one()" }
    def two() { println "method two()" }
}

def callMethod( obj, methodName ) {
    obj."$methodName"()
}

def dyn = new Dynamic()

callMethod( dyn, "one" )               //prints 'method one()'
callMethod( dyn, "two" )               //prints 'method two()'
dyn."one"()                            //prints 'method one()'
2
répondu lifeisfoo 2014-03-23 09:53:22

comment construire un arbre JSON en quelques lignes à groovy ?

1) Définissez votre arbre avec auto-référentiel withDefault fermeture

def tree // declare  first before using a self reference
tree = { ->  [:].withDefault{ tree() } }

2) Créez votre propre arbre JSON

frameworks = tree()
frameworks.grails.language.name = 'groovy'
frameworks.node.language.name = 'js'

def result =  new groovy.json.JsonBuilder(frameworks)

qui donne: {"grails":{"language":{"name":"groovy"}},"node":{"language":{"name":"js"}}}

2
répondu ludo_rj 2014-03-23 20:04:04

la Sécurité de la navigation de l'opérateur

le Safe Navigation operator est utilisé pour éviter une NullPointerException. Généralement, lorsque vous avez une référence à un objet, vous pourriez avoir besoin de vérifier qu'il n'est pas null avant d'accéder aux méthodes ou aux propriétés de l'objet. Pour éviter cela, l'opérateur de navigation sûre retournera simplement null au lieu de lancer une exception, comme ceci:

def person = Person.find { it.id == 123 }        // find will return a null instance    
def name = person?.name                          // use of the null-safe operator prevents from a NullPointerException, result is null
2
répondu Pankaj Shinde 2015-04-13 12:28:48

décélération à variables multiples

1 )déclarations de variables multiples en ligne simple

def (a,b,c) = [1,2,3]

2) en utilisant des déclarations de type différentes.

def (String a, int b) = ['Groovy', 1]
1
répondu Zulqarnain Satti 2016-02-11 07:34:46

opérateur de coercition

l'opérateur de coercition (as) est une variante de la coulée. La coercition convertit l'objet d'un type à un autre sans qu'il soit compatible avec la cession. Prenons un exemple:

entier x = 123

String s = (String) x

Integer n'est pas assignable à une chaîne, donc produira une ClassCastException à l'exécution Cela peut être corrigé en utilisant coercition à la place:

entier x = 123 Chaîne s = x comme chaîne

Integer n'est pas assignable à une chaîne, mais l'utilisation de as va la forcer à une chaîne

0
répondu Ishwor 2015-12-15 15:23:05