Groovy: значение «это» внутри замыкания - PullRequest
10 голосов
/ 04 мая 2009

Следующий пример адаптирован из 'Groovy in Action'

class Mother {

    Closure birth() {                            
        def closure = { caller ->
            [this, caller]
        }
        return closure
    }
}                    

Mother julia = new Mother()
closure = julia.birth()                                
context = closure.call(this)                             

println context[0].class.name        // Will print the name of the Script class
assert context[1] instanceof Script 

Согласно книге, значение this внутри замыкания является самой внешней областью (то есть областью, в которой объявлено julia). Правильно ли я полагаю, что

  • this внутри замыкания соответствует объему, в котором вызывается замыкание?
  • в закрытии, показанном выше, this и caller относятся к одной и той же области видимости?

Спасибо, Дон

Ответы [ 4 ]

10 голосов
/ 26 сентября 2012

"this" в блоке означает в Groovy всегда (будь то обычный Java-подобный блок или Closure) окружающий класс (экземпляр). «owner» является свойством Closure и указывает на внедряемый объект, который является либо классом (экземпляром), а затем таким же, как «this», или другим Closure. Я бы полностью забыл про сферу действия этой части. Таким образом, в вышеприведенном случае правильно, что «это» относится к матери.

А теперь, чтобы усложнить ситуацию ... "это" и неявное это не то же самое в Groovy. Так что если у вас есть Closure {foo()} и {this.foo()}, вы можете получить разные результаты. this.foo() всегда будет преобразован в класс встраивания, тогда как только foo() будет разрешен с использованием мета-объектного протокола Groovy (MOP) и может указывать на что-то совершенно другое. Например, сборщик может установить делегат для этого Closure и перехватить вызов метода для стандартного построителя Groovy. Во всяком случае ... именно поэтому эта часть называется динамической областью действия.

Историческая справка: До Groovy 1.0 «этим» был сам объект Closure. Но был изменен, потому что на самом деле вызов this.foo() стал невозможным, если строитель перехватил все вызовы. тогда у вас не было возможности вызывать локальные методы изнутри компоновщика. Было много попыток изменить стандартную стратегию разрешения - и большие эмоциональные дискуссии тоже. Но, в конце концов, изменение «this» для ссылки на класс встраивания стало простым решением проблемы и больше соответствует людям, пришедшим с Java, плюс оно позволит вам легко обойти MOP, если вы настаиваете.

9 голосов
/ 04 мая 2009

Взгляните на страницу 144

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

На ваши вопросы;

это внутри замыкания соответствует объему, в котором называется замыкание?

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

В любом случае, ответ на ваш вопрос по-прежнему "нет".

в закрытии, показанном выше, это и вызывающий абонент относятся к одной и той же области видимости?

Боюсь, что нет.

Имейте в виду, что страницы 143 и 144 в Groovy in Action нуждаются в некоторых исправлениях

http://groovy.canoo.com/errata/erratum/show/5

http://groovy.canoo.com/errata/erratum/show/8

5 голосов
/ 04 сентября 2012
{
    def self = ({ owner })()
}

владелец: окружающий объект (это или окружающее замыкание ).

1 голос
/ 27 января 2011

Саке говорит: « это - это замыкание , а не объект, в котором замыкание [строится]». Но когда мы запускаем этот скрипт, мы обнаруживаем, что это - Мать, а не Закрытие.

...