Groovy文法学習(四)閉包まとめ
groovyの閉パッケージ、すなわちClosure.lambdaやkotlinに接触したことがある人は、javaにsetxxxListenerのような方法があれば、直接1つのインタフェース(インタフェースが1つしかない場合は関数インタフェースと呼ばれます)に転送されることを知っているに違いありません.それからインタフェースの中の方法の外装の1階は完全に役に立たなくて、それからlambda式はこの問題を解決してjava 8の中で使用することができます.Closureはこのような形式に似ていますが、閉パッケージにはより多くの実装があります.以下にまとめます.
一、閉包の使用
(一)単純閉パケットの定義使用、もちろん閉パケットとメソッドの意向、最後の値はデフォルトで戻り値
結果:
(二)閉包パラメータ、デフォルトパラメータ、パラメータ伝達、指定パラメータ
結果:
(三)インタフェースとの置き換え
1、一般代替
結果:
2、複数の方法の代替
結果:
二、閉パッケージの代理メカニズム
closureは独特のエージェントメカニズムを持っています.私たちがClosureというクラスに突っ込むと、注釈が非常に詳しく書かれていることに気づきます.また、例もあります.注釈を直接見ると、ほとんどの内容が理解できます.良心ですね.例があればもっと理解できます.本当に安定しています.まずこの部分を見てみましょう
実はここはちょっとわかりませんが、doCallかcallか、実はcallの方法を使うのがいいですね.でも、ポイントではありません.私は主にこの2つの方法に注目して、この2つの方法は閉じたパケットのパラメータの個数とタイプを取得して、直接テストします.正直、指定した閉包パラメータのタイプを表示する方法が見つかりませんでしたが、大神さんが教えてくれたかどうか、感謝しています.
結果:
エージェントのポリシー
閉パケットには3つの変数があり、デフォルトではthisが定義したときに存在するクラスのthis静的閉パケットの中でclass ownerが定義したときに存在するクラスのオブジェクトdelegateのデフォルトはownerです.
delegateを使用すると、エージェントのポリシーは全部で5つあります.OWNER_FIRSTオーナー優先DELEGATE_FIRSTエージェント優先OWNER_ONLY所有者のみDELEGATE_ONLYエージェントのみTO_SELFは自身のみ
まず変数への影響を見てみましょう.
それぞれ5つのポリシーで結果をテスト
一見して明らかですが、局所変数にとってはポリシーによって選択されますが、実は簡単です.では、方法については、
このように書くと、ポリシーが何であれselfが呼び出されます.つまり、ローカル変数はロックされています.
このクローズドバッグを外すと、結果が違います.
閉パッケージdelegate,owner,thisを手動で指定する場合はrehydrate()を使用して、delegate,owner,thisに対応する3つのパラメータを渡すことができます.新しい閉パッケージを返して使用します.
結果:
この特性を利用してGradleに詳しい人ならDSLの基本原理が理解できる.それでは閉包してここまでまとめて、間違いがあればコメントエリアで指摘してください.
一、閉包の使用
(一)単純閉パケットの定義使用、もちろん閉パケットとメソッドの意向、最後の値はデフォルトで戻り値
def closure={
println "this is a closure"
}
closure.call()
closure()
結果:
this is a closure
this is a closure
(二)閉包パラメータ、デフォルトパラメータ、パラメータ伝達、指定パラメータ
def closure={
i="5",j->
println "closure $i $j"
}
//map , ,
//
closure('i':"5",'j':"10",5)
closure('i':"5",'j':"10")
closure("ja")
def newClosure = closure.ncurry(1,'6')
newClosure('7')
結果:
closure [i:5, j:10] 5
closure 5 [i:5, j:10]
closure 5 ja
closure 7 6
(三)インタフェースとの置き換え
1、一般代替
interface Ic{
void call()
}
interface IIc{
void call()
}
def test(c){
c()
}
def test2(IIc c){
c()
}
test {
println "closure"
}
test(new Ic(){
@Override
void call() {
println "closure"
}
})
test2{
println "closure"
}
結果:
closure
closure
closure
2、複数の方法の代替
interface IcTeste{
void test1();
void test2();
void test3();
}
def test( c){
c.test1();
c.test2();
c.test3();
}
def closure={
println "test"
} as IcTeste
test(closure)
結果:
test
test
test
二、閉パッケージの代理メカニズム
closureは独特のエージェントメカニズムを持っています.私たちがClosureというクラスに突っ込むと、注釈が非常に詳しく書かれていることに気づきます.また、例もあります.注釈を直接見ると、ほとんどの内容が理解できます.良心ですね.例があればもっと理解できます.本当に安定しています.まずこの部分を見てみましょう
* To be able to use a Closure in this way with your own
* subclass, you need to provide a doCall method with any
* signature you want to. This ensures that
* {@link #getMaximumNumberOfParameters()} and
* {@link #getParameterTypes()} will work too without any
* additional code.
実はここはちょっとわかりませんが、doCallかcallか、実はcallの方法を使うのがいいですね.でも、ポイントではありません.私は主にこの2つの方法に注目して、この2つの方法は閉じたパケットのパラメータの個数とタイプを取得して、直接テストします.正直、指定した閉包パラメータのタイプを表示する方法が見つかりませんでしたが、大神さんが教えてくれたかどうか、感謝しています.
def c ={
i ,j->
println "groovy $i $j"
}
println c.getMaximumNumberOfParameters()
println c.getParameterTypes()
結果:
2
[class java.lang.Object, class java.lang.Object]
エージェントのポリシー
閉パケットには3つの変数があり、デフォルトではthisが定義したときに存在するクラスのthis静的閉パケットの中でclass ownerが定義したときに存在するクラスのオブジェクトdelegateのデフォルトはownerです.
delegateを使用すると、エージェントのポリシーは全部で5つあります.OWNER_FIRSTオーナー優先DELEGATE_FIRSTエージェント優先OWNER_ONLY所有者のみDELEGATE_ONLYエージェントのみTO_SELFは自身のみ
まず変数への影響を見てみましょう.
class Test {
def x = 30
def y = 40
def run() {
def data = [x: 10, y: 20]
def cl = { y = x + y }
cl.delegate = data
cl.resolveStrategy = Closure.DELEGATE_FIRST
switch (cl.resolveStrategy) {
case Closure.DELEGATE_FIRST:
println "DELEGATE_FIRST"
break;
case Closure.DELEGATE_ONLY:
println "DELEGATE_ONLY"
break;
case Closure.OWNER_ONLY:
println "OWNER_ONLY"
break;
case Closure.TO_SELF:
println "TO_SELF"
break;
case Closure.OWNER_FIRST:
println "OWNER_FIRST"
break;
}
println "cl=" + cl()
println "x" + x
println "y" + y
}
}
new Test().run()
それぞれ5つのポリシーで結果をテスト
DELEGATE_FIRST|DELEGATE_ONLY
cl=30
x30
y40
===============================
OWNER_ONLY|OWNER_FIRST
cl=70
x30
y70
===============================
TO_SELF
Caught: groovy.lang.MissingPropertyException: No such property: x for class: Test$_run_closure1
一見して明らかですが、局所変数にとってはポリシーによって選択されますが、実は簡単です.では、方法については、
class Delegate {
def fun() {
println "delegate"
}
}
def fun(){
println "owner"
}
def cl = {
def fun = {
println "self"
}
fun()
}
cl.delegate = new Delegate()
cl.resolveStrategy = Closure.OWNER_FIRST
switch (cl.resolveStrategy) {
case Closure.DELEGATE_FIRST:
println "DELEGATE_FIRST"
break;
case Closure.DELEGATE_ONLY:
println "DELEGATE_ONLY"
break;
case Closure.OWNER_ONLY:
println "OWNER_ONLY"
break;
case Closure.TO_SELF:
println "TO_SELF"
break;
case Closure.OWNER_FIRST:
println "OWNER_FIRST"
break;
}
cl()
このように書くと、ポリシーが何であれselfが呼び出されます.つまり、ローカル変数はロックされています.
def fun = {
println "self"
}
このクローズドバッグを外すと、結果が違います.
DELEGATE_FIRST|DELEGATE_ONLY
delegate
============================
OWNER_ONLY|OWNER_FIRST
owner
============================
TO_SELF
Caught: groovy.lang.MissingMethodException: No signature of method: test$_run_closure1.fun() is applicable for argument types: () values: []
閉パッケージdelegate,owner,thisを手動で指定する場合はrehydrate()を使用して、delegate,owner,thisに対応する3つのパラメータを渡すことができます.新しい閉パッケージを返して使用します.
def fun(Closure c) {
def b=c.rehydrate('123','234','456')
b.call()
}
fun {
println this
println delegate
println owner
}
結果:
456
123
234
この特性を利用してGradleに詳しい人ならDSLの基本原理が理解できる.それでは閉包してここまでまとめて、間違いがあればコメントエリアで指摘してください.