[英]Groovy closure does not modify a value in delegated object
下面顯示的 Groovy 代碼包含閉包和一個方法。 該格式更改標簽並期望收到該更改標簽顯示了問題和要求。
def method (String a, Closure c) {
Query q = new Query()
q.a = a
c.delegate = q
c.call()
def str = q.str
}
class Query
{
def str
def a
void key (String str, Closure cls) {
this.str = str
Pass p = new Pass()
p.a=a
cls.delegate=p
cls.call()
def val=p.a // Expcted to receive that change
println val
}
class Pass
{
String a
}
}
method("got") {
key ("got"){
a=a.toUpperCase() // Format Changed here
println a
}
}
實際輸出是:
GOT
got
但我的預期輸出是:
GOT
GOT
為什么a = a.toUpperCase()
在cls.call()
之后不會改變p
對象中的值? 如何傳遞這種變化?
您必須將key(String str, Closure cls)
方法中cls
委托解析策略更改為:
cls.resolveStrategy = Closure.DELEGATE_FIRST
默認策略是Closure.OWNER_FIRST
。 在 Groovy 腳本的情況下,這意味着此閉包的所有者是由 Groovy 生成以運行腳本的類的實例。 對於您的 Groovy 腳本,該類如下所示:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.Binding;
import groovy.lang.Closure;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.GeneratedClosure;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class my_groovy_script extends Script {
public my_groovy_script() {
CallSite[] var1 = $getCallSiteArray();
}
public my_groovy_script(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, my_groovy_script.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
class _run_closure1 extends Closure implements GeneratedClosure {
public _run_closure1(Object _thisObject) {
CallSite[] var3 = $getCallSiteArray();
super(my_groovy_script.this, _thisObject);
}
public Object doCall(Object it) {
CallSite[] var2 = $getCallSiteArray();
class _closure2 extends Closure implements GeneratedClosure {
public _closure2(Object _thisObject) {
CallSite[] var3 = $getCallSiteArray();
super(_run_closure1.this, _thisObject);
}
public Object doCall(Object it) {
CallSite[] var2 = $getCallSiteArray();
Object var3 = var2[0].call(var2[1].callGroovyObjectGetProperty(this));
ScriptBytecodeAdapter.setGroovyObjectProperty(var3, _closure2.class, this, (String)"a");
return var2[2].callCurrent(this, var2[3].callGroovyObjectGetProperty(this));
}
public Object doCall() {
CallSite[] var1 = $getCallSiteArray();
return this.doCall((Object)null);
}
}
return var2[0].callCurrent(this, "got", new _closure2(this.getThisObject()));
}
public Object doCall() {
CallSite[] var1 = $getCallSiteArray();
return this.doCall((Object)null);
}
}
return var1[1].callCurrent(this, "got", new _run_closure1(this));
}
public Object method(String a, Closure c) {
CallSite[] var3 = $getCallSiteArray();
Query q = (Query)ScriptBytecodeAdapter.castToType(var3[2].callConstructor(Query.class), Query.class);
ScriptBytecodeAdapter.setGroovyObjectProperty(a, my_groovy_script.class, q, (String)"a");
ScriptBytecodeAdapter.setGroovyObjectProperty(q, my_groovy_script.class, c, (String)"delegate");
var3[3].call(c);
Object str = var3[4].callGroovyObjectGetProperty(q);
return str;
}
}
正如您所看到的,每個 Groovy 腳本實際上都是一個擴展groovy.lang.Script
類的類。 這個類有一件重要的事情 - 它覆蓋:
public Object getProperty(String property)
public void setProperty(String property, Object newValue)
如果您查看這兩種方法的源代碼,您將看到它使用binding
對象來存儲和訪問閉包范圍內的所有變量。 這就是為什么您傳遞給Query.key(String str, Closure cls)
不會修改Pass
類a
字段,而是創建a
具有值GOT
的本地綁定a
。 您可以通過將 Closure 的解析策略更改為Closure.DELEGATE_FIRST
來更改此行為。 這將cls.delegate
,因為您明確地將cls.delegate
設置為p
instance,因此閉包將首先在p
instance 中查找字段a
。 我希望它有幫助。
def method(String a, Closure c) {
Query q = new Query()
q.a = a
c.delegate = q
c.call()
def str = q.str
}
class Query {
def str
def a
void key(String str, Closure cls) {
this.str = str
Pass p = new Pass()
p.a = a
cls.delegate = p
cls.resolveStrategy = Closure.DELEGATE_FIRST
cls.call()
def val = p.a // Expcted to receive that change
println val
}
class Pass {
String a
}
}
method("got") {
key("got") {
a = a.toUpperCase() // Format Changed here
println a
}
GOT
GOT
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.