欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Groovy闭包

程序员文章站 2022-06-19 14:57:35
文章目录1、优雅介绍闭包2、闭包场景2.1、使用迭代器(iterators)2.2、 使用一个协议处理资源3、声明闭包3.1、简单申明3.2、为声明赋值3.3、闭包对应多个方法3.4、 比较可选值4、使用闭包4.1、调用闭包4.2、更多闭包能力5、理解闭包域5.1、简单变量域5.2、观察闭包域5.3、经典累加测试6、闭门返回值7、支持设计模式7.1、观察者模式8、总结1、优雅介绍闭包一段代码块作为一个对象看待it作为提供闭包的默认名称2、闭包场景2.1、使用迭代器(iterators)//...

1、优雅介绍闭包

  • 一段代码块作为一个对象看待
  • it作为提供闭包的默认名称

2、闭包场景

2.1、使用迭代器(iterators)

// java 5
for (ItemType item : list){
  // 具体逻辑
}

// groovy 对象
list.each{ item -> 
  // 具体逻辑
}
  
// java 8 with lambda
list.stream().forEach((item) -> {
  // 具体逻辑
})  

// java 8 groovy 闭包
list.stream().forEach{println it}


2.2、 使用一个协议处理资源

  • new File('myfile.txt').eachLine{println it}
    
    // handler
    //java a @FuncionalInterface in java 8
    interface ResourceUser{
      void use(Resource resource)
    }
    // 使用
    resourceHandler.handle(new ResourceUser(){
      public void use (Resource resource){
        resource.doSomething()
      }
    });
    
    // groovy 
    resourceHandler.handle{ resource -> resource.doSomething()}
    

3、声明闭包

3.1、简单申明

  • /**
     * 简单闭包申明
     * @author liangchen* @date 2020/11/4
     */
    class SimpleDeclarationDemo {
    
        static void main(String[] args) {
    
            // 自定义参数名 counter
            def  log = ""
            (1..10).each { counter -> log += counter}
    
            assert  log == '12345678910'
    
            // it就是默认参数名称
            log = ''
            (1..10).each { log += it }
            assert  log == '12345678910'
    
        }
    }
    

3.2、为声明赋值

  • /**
     * 闭包定义
     * @author liangchen* @date 2020/11/4
     */
    class AssignmentClosure {
    
    
        static void main(String[] args) {
           AssignmentClosure assignmentClosure =  new AssignmentClosure()
            def t= 1111 
            assignmentClosure.printers.call(t)
        }
        // 闭包定义方式一
        def printers = { line -> println line}
    
        // 方式二
        Closure getPrinter(){
            return { line -> println line}
        }
    }
    

3.3、闭包对应多个方法

  • 闭包也可以用于查询 过滤条件

    • /**
       * @author liangchen* @date 2020/11/4
       */
      class MultiMethodSample {
      
          static void main(String[] args) {
              SizeFilter filter1 = new SizeFilter(limit: 6)
              SizeFilter filter2 = new SizeFilter(limit: 5)
      
              // 方法闭包赋值
              Closure sizeUpTo6 =  filter1.&sizeUpTo
              def words = ['long string', 'medium', 'short', 'tiny']
      
              assert 'medium' == words.find(sizeUpTo6)
              assert 'short' == words.find(filter2.&sizeUpTo)
      
              //=========
              // 根据不同参数找到不同闭包对应方法
              MultiMethodSample methodSample =  new MultiMethodSample()
              Closure multi = methodSample.&mysteryMethod
              assert  10 == multi('string arg')
              assert  3 == multi(['list','of','values'])
              assert 14 == multi(6, 8)
      
      
          }
      
          int mysteryMethod (String value){
              return value.length();
          }
      
          int mysteryMethod(List list) {
              return list.size();
          }
      
          int mysteryMethod(int x, int y) {
              return x + y
          }
      
      }
      
      /**
       * 大小过滤
       */
      class SizeFilter {
          Integer limit
      
          boolean sizeUpTo(String value) {
              return value.size() <= limit
          }
      }
      
      

3.4、 比较可选值

4、使用闭包

4.1、调用闭包

  • 有点类似

  • /**
     * 闭包定义规则,比如做一下,四则运算
     * @author liangchen* @date 2020/11/4
     */
    class CallingClosureDemo {
    
        static void main(String[] args) {
            def adder = { x, y -> return x + y }
    
            assert  adder(4,3) == 7
    
            assert adder.call(2, 6) == 8
            def slow = benchmark(10000) { (int) it / 2 }
            def fast = benchmark(10000) { it.intdiv(2) }
            assert  fast * 2 < slow
    
            def plus = calculate(1, 2) { x, y -> x + y }
            assert plus == 3
    
            def multi = calculate(1, 2) { x, y -> x * y }
            assert multi == 2
    
    
        }
    
        def static benchmark(int repeat, Closure worker){
            def start = System.nanoTime()
    
            repeat.times {worker(it)}
            def stop = System.nanoTime()
            return stop - start
        }
    
        def static calculate(int num1, int num2, Closure worker) {
           worker(num1, num2)
        }
    }
    
    

4.2、更多闭包能力

  • /**
     * 更多闭包特性 和 curry
     * @author liangchen* @date 2020/11/5
     */
    class MoreClosureDemo {
        static void main(String[] args) {
            //判断closure 参数是1
            assert numParams {one ->} == 1
            //判断closure 参数数量是2
            assert numParams { one, two -> } == 2
    
            // 判断参数类型
            assert paramTypes { String s -> } == [String]
            assert paramTypes {Number n, Date d ->} == [Number, Date]
    
            // currying 填充未知数
            def mult = { x, y, z -> return x * y * z }
            // {x,y,z -> return 2 * y * z}
            def twoTimes = mult.curry(2)
            // {x,y,z -> return 2 * 3 * z}
            def threeTimes = twoTimes.curry(3)
            // {x,y,z -> return 2 * 3 * 60}
            assert threeTimes(10) == 60
    
            // 将参数归纳一下, 有点类似定义抽象问题
            def configurator = {
                format, filter, line -> filter(line) ? format(line) : null
            }
            def appender = {config, append ,line  ->
                def out = config(line)
                if(out) append(out)
            }
            def dateFormatter = { line -> "${new Date()} : $line" }
    
            def debugFilter = { line -> line.contains('debug') }
            def consoleAppender = {line -> println line}
    
            def myConf = configurator.curry(dateFormatter, debugFilter)
            def myLog = appender.curry(myConf, consoleAppender)
            myLog("here is some debug message")
            myLog("this will not be printed")
    
    
            // 合并组合closure
            // currying 填充未知数
             mult = { x, y -> return x * y  }
            // {x,y,z -> return 2 * y * z}
            twoTimes = mult.curry(2)
            def fourTimes = twoTimes >> twoTimes
            def  eightTimes = twoTimes << fourTimes
    
            assert  eightTimes(1) == twoTimes(fourTimes(1))
    
            // 内存化 提高访问速度
            def fib
            fib = { it < 2 ? 1 : fib(it - 1) + fib(it - 2) }
            fib = fib.memoize()
            assert fib(40) == 165_580_141
    
            // trampoline 蹦床 防止递归栈溢出
            def last
            last = { it.size() == 1 ? it.head() : last.trampoline(it.tail()) }
            last = last.trampoline()
    
            assert  last(0..10_000) == 10_000
    
        }
    
    
        def static numParams(Closure closure) {
            closure.getMaximumNumberOfParameters()
        }
    
        def static paramTypes(Closure closure) {
            closure.getParameterTypes()
        }
    
    
    }
    
    

5、理解闭包域

  • 那个变量可以获得
  • 什么时候或怎么绑定到这值
  • 你怎么样控制这个作用域

5.1、简单变量域

  • /**
     * 闭包的作用域
     * @author liangchen* @date 2020/11/5
     */
    class ClosureScopeDemo {
    
        static void main(String[] args) {
            def x = 0
            10.times {
                x++
            }
            assert  x == 10
        }
    }
    
    

5.2、观察闭包域

  • /**
     * Closure域
     * @author liangchen* @date 2020/11/6
     */
    class InvestigateClosureScope {
        static void main(String[] args) {
    
            Mother julia = new Mother()
            def closure = julia.birth('param')
            // 获取closure上下文
            def context = closure.call()
    
            assert context[0] == julia
            assert context[1, 2] == ['prop', 'method']
            assert context[3, 4] == ['local', 'param']
            // 对象
            assert closure.thisObject == julia
            assert  closure.owner == julia
    
            // 代理
            assert closure.delegate == julia
            assert closure.resolveStrategy == Closure.OWNER_FIRST
    
            def map = [:]
            // map 进行代理
            map.with {
                a = 1
                b = 2
            }
            assert map == [a: 1, b: 2]
    
        }
    
    
    }
    
    class Mother {
        def prop = 'prop'
        def method(){
            'method'
        }
        Closure birth(param){
            def local = 'local'
            def closure = {
                [this, prop, method(), local, param]
            }
            return closure
        }
    }
    
    

5.3、经典累加测试

  • 累加器

  • /**
     *
     * groovy 累加器
     * @author liangchen* @date 2020/11/6
     */
    class AccumulatorTest {
    
        static void main(String[] args) {
            def accumulator = foo(1)
           // 1+2 ==3
            assert  accumulator(2) == 3
            // 3+1 ==4
            assert accumulator(1) == 4
            // 4+1==5
            assert accumulator(1) == 5
    
        }
    
       static def foo(n) {
            return { n += it }
    
        }
    
    }
    
    

6、闭门返回值

  • /**
     * closure 返回值
     * @author liangchen* @date 2020/11/6
     */
    class ClosureReturnDemo {
    
    
         static void main(String[] args) {
             // 不需要return
             def doubled =  [1,2,3].collect{it * 2}
             assert doubled == [2,4,6]
    
             // return 关键字
             doubled =  [1,2,3].collect { return it * 2 }
             assert doubled == [2,4,6]
    
             // 偶数 * 2, 奇数直接返回
             def odd= [1,2,3].collect {
                 if(it % 2 ==0) return it * 2
                return it
             }
             assert odd == [1,4,3]
         }
    }
    
    

7、支持设计模式

7.1、观察者模式

  • /**
     * 观察者模式
     * @author liangchen* @date 2020/11/6
     */
    class VisitorPatternDemo {
    
        static void main(String[] args) {
            def picture = new Drawing(shapes: [new Square(width: 1), new Circle(radius: 1)])
    
            def total = 0
            // 累加的Closure
            picture.accept {total += it.area()}
    
            println "The shapes in this drawing cover an area of $total units."
    
            println "The individual contributions are: "
    
            picture.accept {println it.class.name + ":" + it.area()}
        }
    }
    class Drawing {
        List shapes
    
        def accept(Closure yield){
            shapes.each {it.accept(yield)}
        }
    }
    
    class Shape {
        def accept(Closure yield){
            yield(this)
        }
    }
    
    class Square extends  Shape{
        def width
        def area() { width**2 }
    
    }
    class Circle extends Shape{
        def radius
    
        def area() { Math.PI * radius**2 }
    
    }
    
    
    

8、总结

  • 一段代码也是算是一个Closure
  • 有点类似java lambda风格

本文地址:https://blog.csdn.net/m0_37355951/article/details/110244178