первый общий обзор отличного сценария:
// file: SomeScript.groovy
x = 1
def x = 2
println x
println this.x
примерно компилируется как:
class SomeScript extends groovy.lang.Script {
def x
def run() {
x = 1
def x = 2
println x // 2
println this.x // 1
}
}
в скрипте groovy (грубо говоря, в файле без объявления класса) присвоение значения неопределенной переменной интерпретируется как присвоение поля.
ваш пример пытается определить замыкание с параметром с именем fruit
.
если вы определили fruit
с помощью ключевого слова def
, вы получите сообщение об ошибке, поскольку имя уже взято как локальная переменная, и вы не можете дублировать имя локальной переменной.
когда вы опускаете ключевое слово def
, вы фактически присваиваете значение полю класса, сгенерированного для скрипта, и, таким образом, имя fruit
может быть переопределено как локальная переменная.
в отношении областей, это очень похоже на Java ...
в примере вы можете видеть, что x
определяется сначала как поле, а затем как переменная, локальная для метода run()
. в этом нет ничего плохого, и вы можете получить доступ как к переменной, так и к полю.
но как только вы определите локальную переменную, вы не сможете создавать дубликаты.
редактировать -
Я должен был добавить это, прежде чем кто-нибудь поймет меня неправильно: перевод не совсем такой (таким образом, «примерно»). Вместо поля вы добавляете значение для привязки сценария, совсем как args
для сценариев командной строки или request
, session
или response
для groovlets.
но это гораздо более длинная история ...
хорошо, если вы действительно хотите знать, просто спросите еще раз, и я объясню это лучше
редактировать 2 -
я просто не могу оставить это так, если вам когда-нибудь понадобится дополнительная информация ...
каждый скрипт Groovy имеет поле с именем binding
, экземпляр groovy.lang.Binding
или один из его подклассов.
эта привязка в основном карта с методами setVariable
и setVariable
.
когда вы опускаете ключевое слово def
при назначении значения в скрипте, вы фактически вызываете метод setVariable
, а когда вы делаете что-то вроде this.x
, вы вызываете метод getVariable
.
это на самом деле потому, что класс groovy.lang.Script
переопределяет методы getProperty
и setProperty
, чтобы сначала вызывать эти методы. Вот почему они ведут себя как поля.
Вы могли также заметить, что с этими переменными не связан тип ... это потому, что мы имеем дело с Map
внутри привязки.
стандартные скриптовые скрипты создаются с экземпляром привязки с набором args
для массива параметров.
другие, например groovy.servlet.ServletBinding
, определяют больше переменных и поведения, например, блокируют присвоение определенных переменных или добавляют ленивые возможности инициализации ...
тогда истинная причина ошибки заключается в том, что ... если ключевое слово def
не используется, fruits
не является реальной переменной. тем не менее, я считаю, что поведение несколько аналогично области.
прости за все это.
я не был удовлетворен своим собственным упрощением: S