2012-04-26 12 views
6

Groovy parece tener un comportamiento muy desagradable asociado con "Groovy Beans" y cierres que pueden causar que enmascare las variables locales en ciertas circunstancias.¿Choque maravilloso entre captador automático de propiedades, variables locales y cierres?

¿Es este comportamiento conocido y hay alguna documentación en alguna parte que detalla esto? Perdí mucho tiempo tratando de averiguar lo que no estaba funcionando ...

Considere el siguiente código:

class TestClass { 

    def doIt(Closure closure) { 
     closure.setDelegate(this) 
     closure.call() 
    } 

    def getRevision() { 
     return "testclass revision" 
    } 
} 

def testIt() { 
    def revision = "testit revision" 

    println "1: " + revision + " (expect: testit)" 

    TestClass tester = new TestClass() 
    tester.doIt { 
     println "2: " + getRevision() + " (expect: testclass)" 
    } 

    println "3: " + revision + " (expect: testit)" 

    tester.doIt { 
     println "4: " + revision + " (expect: testit)" 
     revision = getRevision() 
     println "5: " + revision + " (expect: testclass)" 
     println "6: ${getRevision()} (expect: testclass)" 
     println "7: " + getRevision() + " (expect: testclass)" 
    } 

    // expect to have been set to testclass value in previous closure 
    println "8: " + revision + " (expect: testclass)" 

    tester.doIt { 
     println "9: ${getRevision()} (expect: testclass)" 
     println "10: " + getRevision() + " (expect: testclass)" 
    } 

    println "11: " + revision + " (expect: testclass)" 
} 

testIt() 

La ejecución de este código produce el siguiente resultado:

1: testit revision (expect: testit) 
2: testclass revision (expect: testclass) 
3: testit revision (expect: testit) 
4: testit revision (expect: testit) 
5: testit revision (expect: testclass) 
6: testit revision (expect: testclass) 
7: testit revision (expect: testclass) 
8: testit revision (expect: testclass) 
9: testclass revision (expect: testclass) 
10: testclass revision (expect: testclass) 
11: testit revision (expect: testclass) 

Mi El problema principal es con 5/6/7. Parece que el simple uso de la variable local revision dentro del cierre "oculta" el método getRevision() en el delegado y lo reemplaza con un getRevision() generado automáticamente por un bean para que coincida con la "propiedad" revision. Si no utilizo la variable revision, las llamadas al getRevision() no invocan este comportamiento del bean.

¡Se agradecerá cualquier información o enlaces a la documentación!

Respuesta

1

Groovy closures have a resolveStrategy property que se pueden utilizar para controlar el orden de resolución. La estrategia predeterminada es buscar la propiedad desde el objeto "propietario" y solo si no se puede encontrar allí para usar el delegado. Creo que estableciendo esto en DELEGATE_FIRST obtendrá el comportamiento que está esperando.

+0

Gracias por la respuesta. Intenté tu sugerencia, pero desafortunadamente no sirvió. Creo que el problema aquí es en tiempo de compilación: usar tanto 'revision' como' getRevision() 'dentro del cierre hace que el compilador groovy crea que tiene que generar un getter para la variable' revision', que luego oculta la versión del delegado. –

Cuestiones relacionadas