2013-06-24 4 views
0

Я пишу большой скрипт Groovy, содержащий ряд глобальных свойств и закрытий. Все Closures используются для добавления новых методов к существующим классам, например .:Как вы можете изменить стратегию решения Closure по умолчанию для скрипта Groovy?

myProperty = 'foo' 
// ...more script code... 

class MyClass { 
    def myProperty = 'default' 
} 
// ...more script code... 

MyClass.metaClass.evaluate = { -> 
    myProperty = 'bar' 
} 

def mc = new MyClass() 
mc.evaluate() 
println mc.myProperty // prints out "default" instead of "bar" 

Моего намерение состоит в закупоривающем myProperty для обозначения класса делегата myProperty, а не глобальной. Я нашел несколько способов справиться с этим:

1) Явным разыменовать delegate внутри крышки:

MyClass.metaClass.evaluate = { -> 
    delegate.myProperty = 'bar' 
} 

def mc = new MyClass() 
mc.evaluate() 
println mc.myProperty // prints out "bar" as desired 

2) Установите стратегию решимости закрытия для DELEGATE_ONLY:

def evalClosure = { -> 
    myProperty = 'bar' 
} 
evalClosure.resolveStrategy = Closure.DELEGATE_ONLY 
MyClass.metaClass.evaluate = evalClosure 

def mc = new MyClass() 
mc.evaluate() 
println mc.myProperty // prints out "bar" as desired 

Я бы предпочел использовать подход № 2, чтобы избежать «делегирования» по всему месту в моих закрытиях, но я не хочу устанавливать стратегию разрешения для каждого создаваемого мною замыкания.

Как сказать Groovy использовать стратегию решения DELEGATE_ONLY для всех закрытий по умолчанию? Возможно ли это?

ответ

1

Там нет никакого способа, я не знаю, чтобы изменить стратегию на делегирование по умолчанию, насколько я могу видеть, у вас есть 2 варианта:

  1. Сплит скрипт на классы (так что вы не имеете сценарий уровень myProperty и уровень класса myProperty в той же области)

  2. Написать способ изменить resolveStrategy и назвать это, когда вы установите metaClass, то есть:

    def only(Closure c) { 
        c.resolveStrategy = Closure.DELEGATE_ONLY 
        c 
    } 
    
    MyClass.metaClass.evaluate = only { -> 
        myProperty = 'bar' 
    } 
    
+0

LOL. У меня был второй подход в качестве ответа вчера, но он не предусматривал, полагая, что OP будет говорить «в любом случае я должен использовать« only() »за закрытие, я бы предпочел использовать' clos.resolveStrategy'. Я также попытался использовать '@ Category', наследование и т. Д., Но я всегда получал дефолтную' resolStrategy'. Тогда я убедил себя, я должен ждать, пока @tim_yates просветят нас. :-) – dmahapatro

+0

@dmahapatro хе-хе, вам следует больше доверять своим инстинктам ;-) Я чувствую, что BDKosher будет не нравится ответ, но я не могу придумать другого способа сделать это (это не вариант для класса CompilerConfiguration) –

+1

Точно. Я также думал, что если «ClosureMetaClass» поможет, но, как вы сказали, это не будет. Для меня это было хорошим упражнением для мозга в течение нескольких часов. :-) – dmahapatro