2008-10-08 4 views
152

В следующем фрагменте кода (взятом из Groovy Semantics Manual page), почему префикс присваивается ключевым словом def?Groovy: в чем цель «def» в «def x = 0»?

def x = 0 
def y = 5 

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

assert x == 5 

Ключевое слово def может быть удалено, и этот фрагмент даст те же результаты. Итак, каков эффект ключевого слова def?

ответ

230

Это синтаксический сахар для основных сценариев. Опуская «Def» ключевое слово ставит переменную в креплениями для текущего сценария и заводной относится к нему (в основном), как глобально контекстными переменной:

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

Использование четкости ключевое слово вместо того, чтобы не поставить переменную в привязок сценариев :

def y = 2 

assert y == 2 

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

печать: «ошибка поймали»

Использование ключевого слова четкости в больших программах очень важно, поскольку это помогает определить область, в которой переменная может быть найдена и может помочь сохранить герметизацию.

Если вы определяете метод в сценарии, он не будет иметь доступ к переменным, которые создаются с «DEF» в теле основного сценария, поскольку они не входят в область действия:

x = 1 
def y = 2 


public bar() { 
    assert x == 1 

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

bar() 

отпечатки «ошибка поймана»

«y» переменная не входит в объем внутри функции. «x» имеет значение, поскольку groovy проверяет привязки текущего скрипта для переменной. Как я сказал ранее, это просто синтаксический сахар, чтобы быстрее и грязнее писать скрипты (часто один лайнер).

Хорошая практика в больших скриптах - всегда использовать ключевое слово «def», чтобы вы не сталкивались с проблемами странного охвата или не вмешивались в переменные, которые вы не планируете использовать.

+10

хорошо indepth ответ! благодаря! – codeLes 2008-10-13 14:50:07

5

На самом деле, я не думаю, что это будет вести себя так же ...

переменные в Groovy все еще требуют декларации, просто не типизированных заявление, так как правая часть, как правило, содержит достаточно информации для Groovy к введите переменную.

Когда я пытаюсь использовать переменную, которую я не объявлял с def или типом, я получаю сообщение об ошибке «Нет такого свойства», поскольку он предполагает, что я использую член класса, содержащего код.

27

Согласно этому page, def является заменой имени типа и может просто рассматривать в качестве псевдонима для Object (т.е. означающий, что вы не заботитесь о типе).

34

Ted's answer отлично подходит для скриптов; Ben's answer является стандартным для классов.

Как говорит Бен, подумайте об этом как о «объекте», но он намного круче, поскольку он не ограничивает вас объектными методами. Это имеет неочевидные последствия в отношении импорта.

например.В этом фрагменте я должен импортировать 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() 

e.g. Но здесь я не могу просто "крыло это, пока все находится на пути к классам

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

Почему вам разрешили «новый FileInputStream (« Test.groovy »). GetChannel()` без импорта? – 2013-11-08 09:13:26

10

Насколько этот единственный сценарий обеспокоен нет практической разницы.

Однако переменные, определенные с использованием ключевого слова «def», рассматриваются как локальные переменные, то есть локальные для этого одного скрипта. Переменные без «def» перед ними сохраняются в так называемом привязке при первом использовании. Вы можете думать о привязке как общей области хранения для переменных и закрытий, которые должны быть доступны «между» сценариями.

Итак, если у вас есть два сценария и их исполнение с тем же GroovyShell, второй скрипт сможет получить все переменные, которые были установлены в первом скрипте без «def».

6

Самое главное, что вы действительно не каждый хотите создать переменную случайно. В сценариях есть что-то вроде ОК, чтобы иметь переменные, созданные по заданию, но в производственном коде это одно из самых больших зол, с которыми вы можете столкнуться. Я не буду рассматривать какой-либо langauge, который позволил бы этой конструкции использоваться в производственном коде.

Я взял интервью у более чем одного места, которое использовало визуальный базис, где они задавали вопрос «Что такое первая строка в любом файле VB», и если вы не ответили «ОПЦИЯ ЭКСПЛИЦИТ», интервью остановилось прямо там. (OPTION EXPLICIT запрещает создание переменных через назначение в VB и заставляет явный «тусклый»)

Вот пример того, почему это плохо. Это будет работать (без проваливать Assert), если вы скопируйте следующий код и вставьте его в заводной сценарий:

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

Он также устраняет некоторые способности компилятора, чтобы помочь вам реорганизовать. Например, если вы переименуете место, в котором вы впервые используете эту переменную, как компилятор знает, чтобы сказать вам, является ли второе использование (назначение) теперь ошибкой, а не новой переменной?

Crap, как это слишком опасно. Даже если он только укусит вас однажды в вашей жизни, он все равно будет стоить больше времени, чем явно указывать переменные тысячи раз на протяжении всей вашей карьеры. Это также становится очевидным для глаз, только там, где оно развязывается, вам не нужно гадать.

В сценариях это довольно нормально, поскольку область действия сценария ограничена, и они не используются повторно и не сохраняются так же сильно, как и перезаписываются, но язык, который позволяет создавать при назначении, просто не готов к производству.

Смежные вопросы