Groovy - Закрытие и связывание, почему этот код не работает? - PullRequest
2 голосов
/ 10 сентября 2010

Я думаю, что это вопрос новичка, но почему он не соответствует последнему утверждению?Я думал, что замыкание привязывает значение к нему, поэтому изменение его из замыкания изменит значение вне замыкания.

def value = 5

def foo(n){

  return {

    ++n

  }
}

def test = foo(value)

assert test() == 6
assert test() == 7

assert value == 7

Спасибо за помощь.

Ответы [ 3 ]

2 голосов
/ 10 сентября 2010

Это кажется странным поведением, но я думаю, что это правильно. Все целые числа событий объектов передаются по ссылке. Вызов foo (value) передает значение в функцию. Переменная 'n' является ссылкой на тот же объект, что и ссылки 'value'. По сути, у вас есть два указателя на один и тот же объект. Когда вы увеличиваете 'n', вы увеличиваете только эту переменную.

Так как класс Integer неизменен, ++ на самом деле делает что-то вроде:

n = n + 1

Это присвоение увеличенного значения переменной n. Переменная 'value', объявленная сверху, все еще указывает на исходный объект 5.

1 голос
/ 10 сентября 2010

Помните, что Integer (тип времени выполнения value) является неизменным.Таким образом, хотя n и value изначально ссылаются на один и тот же объект, при выполнении ++n он создает новый Integer.Ссылка value не обновляется для ссылки на этот новый объект, поэтому, когда выполнение завершается, оно все еще ссылается на исходный объект (5).

0 голосов
/ 10 сентября 2010

Вы присваиваете новое значение имени n, которое отличается от имени value.Вы можете получить желаемое поведение, сделав value изменяемым объектом.Затем вы можете изменить его вместо создания и назначения нового объекта.

Вот простой пример, заключающий значение в список:

def value = [5]

def foo(n){

    return {

        n[0]++
        n
    }
}

def test = foo(value)

assert test() == [6]
assert test() == [7]

assert value == [7]
...