Groovy文法学習(四)閉包まとめ


groovyの閉パッケージ、すなわちClosure.lambdaやkotlinに接触したことがある人は、javaにsetxxxListenerのような方法があれば、直接1つのインタフェース(インタフェースが1つしかない場合は関数インタフェースと呼ばれます)に転送されることを知っているに違いありません.それからインタフェースの中の方法の外装の1階は完全に役に立たなくて、それからlambda式はこの問題を解決してjava 8の中で使用することができます.Closureはこのような形式に似ていますが、閉パッケージにはより多くの実装があります.以下にまとめます.
一、閉包の使用
(一)単純閉パケットの定義使用、もちろん閉パケットとメソッドの意向、最後の値はデフォルトで戻り値
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の基本原理が理解できる.それでは閉包してここまでまとめて、間違いがあればコメントエリアで指摘してください.