kotlin之闭包 kotlin之闭包案例详解
mictoy_朱 人气:0闭包,函数式编程福音
先了解函数式编程(Functional Programming)
概念:它属于“结构化编程”的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用。函数式编程语言最重要的基础是λ运算(Lambda表达式),λ运算的函数可以接受函数当做参数或返回值。
对比函数式编程与面向对象编程
面向对象编程(Object-oriented programming,缩写OOP)
面向对象编程是一种具有对象概念的程序编程范型,它可能包含数据、属性、方法。它将对象作为程序的基本单元,将方法和数据封装其中,以提高软件的重用性、灵活性和扩展性。对象里的程序可以访问及经常修改对象相关联的数据。在面向对象编程里,计算机程序会被设计成彼此相关的对象。
面向对象编程的优点
1.程序的结构化
面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,相比传统的面向过程编程将程序看作一系列函数的集合这种无系统化和结构化的模式,面向对象编程将一系列关联性的数据、方法结构化,封装成类,通过类的对象进行方法、属性调用的方式,可以让编程者更加便于分析、设计和理解。
2.程序的灵活性和可维护性
面向对象编程由于集成、封装、多态的特性,可以更好的设计出高内聚、低耦合的系统 结构,使得系统更灵活、更容易扩展,开发及维护成本更低。
面向对象编程的缺点
- 运行效率较低
面向对象虽然开发效率高但是代码运行效率比起面向过程要低很多,这也限制了面向对象的使用场景不能包括那些对性能要求很苛刻的地方 - 多线程数据不安全
面向对象编程以数据为核心,所以在多线程并发编程中,多个线程同时操作数据的时候可能会导致数据修改的不确定性。
函数式编程优点(可以说就是为了解决面向对象的缺点问题而设计的)
- 线程安全
在函数式编程中,数据全部都是不可变的,所以没有并发编程的问题,是多线程安全的,可以有效降低程序运行中所产生的副作用。对于快速迭代的项目来说,函数式编程可以实现函数与函数之间的热切换而不用担心数据的问题,因为它是以函数作为最小单位的,只要函数与函数的关系正确即可保证结果的正确性。 - 代码可读性高
函数式编程的表达方式更加符合人类日常生活中的语法,代码可读性更强。实现同样的功能函数式编程所需要的代码比面向对象编程要少很多,代码更加简洁明晰。
函数式编程的缺点
运行速度更慢
由于所有的数据都是不可变的,所有的变量在程序运行期间都是一直存在的,非常占用运行资源。同时由于函数式的先天性设计导致性能一直不够。虽然现代的汗水编程语言使用了很多技巧,比如惰性计算等优化运行速度,但始终无法与面向对象相比,当然比面向过程的程序就更慢了
了解完函数式编程,再回归今天的主题——闭包
什么是闭包?
我们都知道,程序的变量分为全局变量和局部变量,全局变量,顾名思义,其作用域是当前文件甚至文件外的所有地方;而局部变量,我们只能再其有限的作用域里获取。
那么,如何在外部调用局部变量呢?答案就是——闭包,与此给闭包下个定义:闭包就是能够读取其他函数内部变量的函数
- 它是运行的环境
- 它持有函数的运行状态
- 它的内部可以定义函数
- 它的内部也可以定义类
首先看个简单的例子
//这是一个返回值为一个函数的高阶函数 fun makeFun():()->Unit{ var conut = 0 return fun(){ //返回一个匿名函数,这个函数持有count的状态 println(++conut) } } fun main() { val makeFun = makeFun() //函数调用,返回一个函数 makeFun() //调用这个返回的函数,此时makeFun持有makeFun()内部变量的状态 makeFun() makeFun() }
运行结果:
在比如一个稍微复杂一点的例子,实现斐波那契数列
//斐波那契数列 fun fibonacci():()->Long{ var first = 0L var second = 1L return fun():Long{ //返回返回值为Long类型的函数 val result = second second += first first = second - first return result } } fun main() { val fibo = fibonacci() //此时,这个返回的函数fibo持有fibonnacci()函数内部变量的状态 println(fibo()) println(fibo()) println(fibo()) println(fibo()) println(fibo()) }
测试运行:
使用迭代器实现斐波那契数列
//使用迭代器实现斐波那契数列(这里就不是返回一个函数而是一个对象了) fun fibonacci2():Iterable<Long>{ var first = 0L var second = 1L return Iterable { object :LongIterator(){ override fun hasNext() = true override fun nextLong(): Long { val result = second second += first first = second - first return result } } } } fun main() { val fibo2 = fibonacci2() for (i in fibo2){ if (i>60) break println(i) } }
运行结果:
加载全部内容