Groovy: какова цель "def" в "def x = 0"?



в следующем фрагменте кода (взято из руководство по семантике Groovy), почему префикс назначения с ключевого слова def?



def x = 0
def y = 5

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

assert x == 5


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

726   6  

6 ответов:

- это синтаксический сахар для основных сценариев. Пропуск ключевого слова " 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", чтобы вы не сталкивались со странными проблемами области видимости или не вмешивались в переменные, которые вы не собираетесь.

Теда отлично подходит для скрипты; Бен стандартная для классов.

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

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

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

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

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

Что касается этого единственного сценария, то нет никакой практической разницы.

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

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

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

я интервьюировал в нескольких местах, которые использовали visual basic, где они задавали вопрос "какова первая строка в любом файле VB" и если вы не ответили "OPTION EXPLICIT", интервью остановилось прямо там. (Опция EXPLICIT запрещает создание переменных через присваивание в VB и заставляет явный "dim")

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

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

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

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

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

Вообще-То, Я не думаю, что он будет вести себя так же...

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

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

Comments

    Ничего не найдено.