it-swarm.com.de

Groovy: Was ist der Zweck von "def" in "def x = 0"?

Warum wird der Zuweisung im folgenden Codeteil (entnommen aus Groovy Semantics-Handbuchseite ) das Schlüsselwort def vorangestellt?

def x = 0
def y = 5

while ( y-- > 0 ) {
    println "" + x + " " + y
    x++
}

assert x == 5

Das Schlüsselwort def kann entfernt werden, und dieses Snippet führt zu denselben Ergebnissen. Was ist der Effekt des Schlüsselworts def?

172
Leonel

Es ist syntaktischer Zucker für grundlegende Skripte. Wenn Sie das Schlüsselwort "def" weglassen, wird die Variable in die Bindungen für das aktuelle Skript eingefügt, und groovy behandelt sie (meistens) wie eine Variable mit globalem Gültigkeitsbereich:

x = 1
assert x == 1
assert this.binding.getVariable("x") == 1

Wenn Sie stattdessen das Schlüsselwort def verwenden, wird die Variable nicht in die Skriptbindungen eingefügt:

def y = 2

assert y == 2

try {
    this.binding.getVariable("y") 
} catch (groovy.lang.MissingPropertyException e) {
    println "error caught"
} 

Drucke: "error caught"

Die Verwendung des Schlüsselworts def in größeren Programmen ist wichtig, da hiermit der Bereich definiert wird, in dem sich die Variable befindet, und die Kapselung beibehalten werden kann.

Wenn Sie in Ihrem Skript eine Methode definieren, hat diese keinen Zugriff auf die Variablen, die mit "def" im Hauptteil des Hauptskripts erstellt wurden, da sie nicht im Gültigkeitsbereich liegen:

 x = 1
 def y = 2


public bar() {
    assert x == 1

    try {
        assert y == 2
    } catch (groovy.lang.MissingPropertyException e) {
        println "error caught"
    }
}

bar()

druckt "Fehler abgefangen"

Die Variable "y" befindet sich nicht im Gültigkeitsbereich der Funktion. "x" ist im Gültigkeitsbereich, da groovy die Bindungen des aktuellen Skripts für die Variable überprüft. Wie ich bereits sagte, ist dies einfach syntaktischer Zucker, um schnelle und schmutzige Skripte schneller abtippen zu können (oft ein Zeilenumbruch).

In größeren Skripten empfiehlt es sich, immer das Schlüsselwort "def" zu verwenden, damit Sie nicht auf seltsame Probleme mit dem Gültigkeitsbereich stoßen oder Variablen stören, die Sie nicht beabsichtigen.

266
Ted Naleid

Teds Antwort eignet sich hervorragend für Skripte; Bens Antwort ist Standard für Klassen.

Stellen Sie es sich, wie Ben sagt, als "Objekt" vor - aber es ist viel cooler, da es Sie nicht auf die Objektmethoden beschränkt. Dies hat gute Auswirkungen auf die Einfuhren.

z.B. In diesem Snippet muss ich FileChannel importieren

// Groovy imports Java.io.* and Java.util.* automatically
// but not Java.nio.*

import Java.nio.channels.*

class Foo {
    public void bar() {
        FileChannel channel = new FileInputStream('Test.groovy').getChannel()
        println channel.toString()
    }
}

new Foo().bar()

z.B. Aber hier kann ich es einfach "beflügeln", solange sich alles auf dem Klassenpfad befindet

// Groovy imports Java.io.* and Java.util.* automatically
// but not Java.nio.*
class Foo {
    public void bar() {
        def channel = new FileInputStream('Test.groovy').getChannel()
        println channel.toString()
    }
}

new Foo().bar()
35
Michael Easter

Entsprechend Seite ist def ein Ersatz für einen Typnamen und kann einfach als Alias ​​für Object angesehen werden (dh als Zeichen dafür, dass Sie sich nicht darum kümmern über den Typ).

29
Ben Hoffstein

In Bezug auf dieses einzelne Skript gibt es keinen praktischen Unterschied.

Mit dem Schlüsselwort "def" definierte Variablen werden jedoch als lokale Variablen behandelt, dh lokal für dieses eine Skript. Variablen ohne das vorangestellte "def" werden bei der ersten Verwendung in einer sogenannten Bindung gespeichert. Sie können sich die Bindung als allgemeinen Speicherbereich für Variablen und Abschlüsse vorstellen, die "zwischen" Skripten verfügbar sein müssen.

Wenn Sie also über zwei Skripte verfügen und diese mit derselben GroovyShell ausführen, kann das zweite Skript alle Variablen abrufen, die im ersten Skript ohne "def" festgelegt wurden.

12
Martin Stephan

Der Grund für "def" ist, groovy mitzuteilen, dass Sie hier eine Variable erstellen möchten. Dies ist wichtig, da Sie niemals versehentlich eine Variable erstellen möchten.

Es ist in Skripten einigermaßen akzeptabel (Groovy-Skripte und Groovysh ermöglichen dies), aber im Produktionscode ist es eines der größten Übel, auf das Sie stoßen können. Aus diesem Grund müssen Sie eine Variable mit def in allen aktuellen Groovy-Codes definieren (alles in einem) Klasse).

Hier ist ein Beispiel, warum es schlecht ist. Dies wird ausgeführt (ohne dass die Bestätigung fehlschlägt), wenn Sie den folgenden Code kopieren und in groovysh einfügen:

bill = 7
bi1l = bill + 3
assert bill == 7

Das Auffinden und Beheben eines solchen Problems kann viel Zeit in Anspruch nehmen. Auch wenn es Sie nur einmal in Ihrem Leben gebissen hat, würde es mehr Zeit kosten, als die Variablen im Laufe Ihrer Karriere Tausende Male explizit zu deklarieren. Es wird auch für das Auge klar, wo es deklariert wird, Sie müssen nicht raten.

Bei unwichtigen Skripten/Konsoleneingaben (wie bei der groovigen Konsole) ist dies einigermaßen akzeptabel, da der Umfang des Skripts begrenzt ist. Ich denke, der einzige Grund, warum Groovy es Ihnen erlaubt, dies in Skripten zu tun, ist die Unterstützung von DSLs auf die gleiche Weise. Ruby (Ein schlechter Kompromiss, wenn Sie mich fragen, aber manche Leute lieben die DSLs)

8
Bill K

Eigentlich, ich nicht denke, es würde sich genauso verhalten ...

variablen in Groovy müssen immer noch deklariert werden, nur nicht die TYPED-Deklaration, da die rechte Seite im Allgemeinen genug Informationen enthält, damit Groovy die Variable eingeben kann.

Wenn ich versuche, eine Variable zu verwenden, die ich nicht mit def oder einem Typ deklariert habe, wird die Fehlermeldung "No such property" angezeigt, da davon ausgegangen wird, dass ich ein Mitglied der Klasse verwende, die den Code enthält.

5
billjamesdev