2008-10-08 18 views

Respuesta

230

Azúcar sintáctico para scripts básicos. La omisión de la palabra clave "def" pone la variable en los enlaces para el script actual y trata maravilloso TI (en su mayoría) como una variable de ámbito global:

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

El uso de la palabra clave def lugar no pone la variable en los enlaces de secuencias de comandos :

def y = 2 

assert y == 2 

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

Lienzo: "error atrapado"

el uso de la palabra clave def en programas de mayor tamaño es importante, ya que ayuda a definir el ámbito en el que se puede encontrar la variable y puede ayudar a preservar la encapsulación.

Si se define un método en el script, no se tiene acceso a las variables que se crean con "def" en el cuerpo del script principal, ya que no están en su alcance:

x = 1 
def y = 2 


public bar() { 
    assert x == 1 

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

bar() 

imprime "error capturado"

La variable "y" no está en el alcance dentro de la función. "x" está en el alcance ya que groovy verificará los enlaces del script actual para la variable. Como dije antes, esto es simplemente azúcar sintáctica para hacer que las secuencias de comandos rápidas y sucias sean más rápidas de escribir (a menudo una línea).

La buena práctica en las secuencias de comandos más grandes es utilizar siempre la palabra clave "def" para no tener problemas de alcance extraño o interferir con las variables que no tiene la intención.

+10

¡buena respuesta en profundidad! ¡Gracias! – codeLes

5

En realidad, yo no piensan que se comportaría de la misma ...

las variables en Groovy todavía requieren declaración, la declaración no TIPIFICADOS, como el lado derecho generalmente contiene suficiente información para Groovy a escribe la variable.

Cuando intento usar una variable que no he declarado con def o un tipo, aparece el error "No such property", ya que supone que estoy usando un miembro de la clase que contiene el código.

27

De acuerdo con esta page, def es un reemplazo para un nombre de tipo y simplemente puede ser pensado como un alias para Object (es decir, que significa que usted no se preocupa por el tipo).

34

Ted's answer es excelente para scripts; Ben's answer es estándar para las clases.

Como dice Ben, piense en ello como "Objeto", pero es mucho más genial ya que no lo restringe a los métodos de Objeto. Esto tiene claras implicaciones con respecto a las importaciones.

p. Ej.En este fragmento, tengo que importar FileChannel

// 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() 

p. Pero aquí sólo puedo 'improvisar', siempre y cuando todo está en la ruta de clase

// 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() 
+0

¿por qué se te permitió 'nuevo FileInputStream ('Test.groovy'). GetChannel()' sin la importación? –

+3

@AlexanderSuraphel "siempre y cuando todo esté en el classpath" – Hanno

10

Por lo que esta única secuencia de comandos se refiere no es ninguna diferencia práctica.

Sin embargo, las variables definidas con la palabra clave "def" se tratan como variables locales, es decir, locales para este script. Las variables sin la "def" delante de ellas se almacenan en una llamada unión al primer uso. Puede pensar en el enlace como un área de almacenamiento general para variables y cierres que deben estar disponibles "entre" scripts.

Por lo tanto, si tiene dos scripts y los ejecuta con el mismo GroovyShell, el segundo script podrá obtener todas las variables que se establecieron en el primer script sin una "def".

6

Lo más importante es que realmente no todos quieren crear una variable por accidente. Está bastante bien en los scripts tener variables creadas en una tarea, pero en el código de producción es uno de los mayores males que puedes encontrar. No consideraré ningún lenguaje que permita que esta construcción sea utilizable en el código de producción.

Me he entrevistado en más de un lugar que utilizaba Visual Basic donde preguntaban "¿Cuál es la primera línea en cualquier archivo VB?" Y si no respondía "OPCIÓN EXPLÍCITA", la entrevista se detenía allí mismo. (OPTION EXPLICIT no permite la creación de variables mediante asignación en VB y fuerza un "dim" explícito)

Aquí hay un ejemplo de por qué es malo. Esto ejecutará (Sin dejar la aserción) si copia el siguiente código y pegarlo en un guión maravilloso:

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

También elimina parte de la capacidad del compilador para ayudarle a refactorizar. Por ejemplo, si cambia el nombre del lugar donde usa la variable por primera vez, ¿cómo sabe el compilador si el segundo uso (una asignación) ahora es un error y no una nueva variable?

Mierda como esta es demasiado peligroso. Incluso si solo te mordía una vez en la vida, aún te costaría más tiempo que declarar explícitamente las variables miles de veces a lo largo de tu carrera. También se vuelve claro para la vista dónde se está retrasando, no tienes que adivinar.

En las secuencias de comandos, está bastante bien porque el alcance del guión es limitado y no se reutilizan y mantienen tanto como se reescriben, pero un lenguaje que permite la creación en la asignación simplemente no está listo para producción.

Cuestiones relacionadas