Это синтаксический сахар для базовых сценариев. Пропуск ключевого слова «def» помещает переменную в привязки для текущего скрипта, а groovy рассматривает ее (в основном) как глобально переменную области видимости:
x = 1
assert x == 1
assert this.binding.getVariable("x") == 1
Использование ключевого слова def вместо этого не помещает переменную в привязки скриптов:
def y = 2
assert y == 2
try {
this.binding.getVariable("y")
} catch (groovy.lang.MissingPropertyException e) {
println "error caught"
}
Печать: «ошибка обнаружена»
Использование ключевого слова def в больших программах важно, поскольку оно помогает определить область, в которой можно найти переменную, и может помочь сохранить инкапсуляцию.
Если вы определите метод в своем скрипте, у него не будет доступа к переменным, созданным с помощью «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», чтобы вы не сталкивались со странными проблемами с областями видимости и не вмешивались в переменные, которые вам не нужны.
new FileInputStream('Test.groovy').getChannel()
без импорта?Согласно этой странице ,
def
является заменой имени типа и может просто рассматриваться как псевдоним дляObject
(т. Е. Означает, что вы не заботитесь о типе).источник
Что касается этого единственного сценария, то практической разницы нет.
Однако переменные, определенные с помощью ключевого слова «def», обрабатываются как локальные переменные, то есть локальные для этого сценария. Переменные без «def» перед ними сохраняются в так называемой привязке при первом использовании. Вы можете рассматривать привязку как общую область хранения переменных и замыканий, которые должны быть доступны «между» сценариями.
Итак, если у вас есть два сценария и вы выполняете их с одним и тем же GroovyShell, второй сценарий сможет получить все переменные, которые были установлены в первом сценарии, без «def».
источник
Причина для "def" заключается в том, чтобы сообщить groovy, что вы намереваетесь создать переменную здесь. Это важно, потому что вы никогда не захотите создать переменную случайно.
Это несколько приемлемо в сценариях (скрипты Groovy и groovysh позволяют вам это делать), но в производственном коде это одно из самых больших зол, с которыми вы можете столкнуться, поэтому вы должны определить переменную с def во всем фактическом коде groovy (что-либо внутри класс).
Вот пример того, почему это плохо. Это запустится (без провала утверждения), если вы скопируете следующий код и вставите его в groovysh:
Подобные проблемы могут занять много времени, чтобы найти и исправить. Даже если это всего лишь один раз в вашей жизни, это все равно будет стоить больше времени, чем явное объявление переменных тысяч раз в течение вашей карьеры. Это также становится ясным для глаз, где именно это объявляется, вам не нужно догадываться.
В неважных сценариях / вводе с консоли (например, в groovy console) это несколько приемлемо, поскольку область действия сценария ограничена. Я думаю, единственная причина, по которой groovy позволяет вам делать это в сценариях, - это поддерживать DSL так, как это делает Ruby (плохой компромисс, если вы спросите меня, но некоторые люди любят DSL)
источник
На самом деле, я не думаю, что он будет вести себя так же ...
переменные в Groovy по-прежнему требуют объявления, но не объявления TYPED, поскольку правая часть обычно содержит достаточно информации, чтобы Groovy мог ввести переменную.
Когда я пытаюсь использовать переменную, которую я не объявил с def или типом, я получаю сообщение об ошибке «Нет такого свойства», поскольку предполагается, что я использую член класса, содержащего код.
источник