2012-04-26 11 views
6

Groovy sembra avere un comportamento molto spiacevole associato a "Groovy Beans" e alle chiusure che possono causare la mascheratura di variabili locali in determinate circostanze.Scontro Groovy tra getter di proprietà automatico, variabili locali e chiusure?

È questo comportamento noto e c'è qualche documentazione da qualche parte che descrive questa roba? Ho sprecato un sacco di tempo a cercare di capire cosa non funzionava ...

Si consideri il seguente codice:

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

L'esecuzione di questo codice produce il seguente output:

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) 

mio il problema principale è con 5/6/7. Sembra che semplicemente utilizzando la variabile locale revision all'interno della chiusura "si nasconda" il metodo getRevision() nel delegato e lo si sostituisca con uno stile beanizzato getRevision() corrispondente alla "proprietà" revision. Se non utilizzo la variabile revision, le chiamate a getRevision() non invocano questo comportamento bean.

Qualsiasi intuizione o collegamenti alla documentazione sarebbero apprezzati!

risposta

1

Chiusure Groovy have a resolveStrategy property che può essere utilizzato per controllare l'ordine di risoluzione. La strategia predefinita consiste nel cercare la proprietà dall'oggetto "proprietario" e solo se non è possibile trovarla per utilizzare il delegato. Credo che settando questo a DELEGATE_FIRST otterrai il comportamento che ti aspetti.

+0

Grazie per la risposta. Ho provato il tuo suggerimento ma sfortunatamente non è stato d'aiuto. Penso che il problema qui sia in fase di compilazione: l'uso di 'revision' e' getRevision() 'all'interno della chiusura fa sì che il compilatore groovy pensi di dover generare un getter per la variabile' revision', che quindi nasconde la versione del delegato. –