本站文章均为Jensen抹茶喵原创,转载务必在明显处注明:
转载自【博客园】 原文连接:http://www.cnblogs.com/JensenCat/p/5112420.htmlhtml
1.什么是闭包java
支持闭包特性一般须要一个嵌套函数,经过执行嵌套函数来改变所在父函数的局部变量状态,父函数保存调用上下文状态,而嵌套函数负责修改状态的改变.(简单来讲就是得支持函数嵌套)api
下面就是一个Lua闭包:闭包
function counter() local cnt = 0 --返回匿名函数也是能够的 local Closure = function() cnt=cnt+1 print("print:"..cnt) end return Closure end function main() local Closure = counter() Closure() --print:1 Closure() --print:2 Closure() --print:3 local newCounter = counter() newCounter() --print:1 newCounter() --print:2 Closure() --print:4 --能够看出他们引用的计数对象是不同的,更像是同一个类的2个不一样的对象 end
2.闭包的做用函数
下面是一个java的类,getName方法获取到了类对象的私有成员变量性能
class Person { private String name; public String getName() { return name; } }
经过上面的方式能够获取到一个类内部的私有属性,一样的,在lua中能够经过某个方法来获取这个方法的局部变量,而后经过这个方法内的方法来读取想要的变量值。lua
function func3() local num3 = 44 function func4() return num3 end return func4 end local func = func3(); print(func())
解释:spa
1.在外部没法获取到func3内部的局部变量,可是func3内部的局部方法func4却能够获取到,所以返回一个func4的引用 ,这样在外部经过这个func4就能够获取到func3的内部变量。code
2.虽然是绕了一个圈子,可是在方法外部却经过这样一个手段获取到了内部的值。而这个方法内的局部方法func4就叫作闭包,按照不少书上的概念,这个方法搭建了方法内部与方法外部的桥梁,使得在外部也能够任意的获取到方法内部的资源。htm
3.可是闭包会形成变量在内存中持久占用,所以会有必定的性能问题,最好不要轻易使用,即使使用也要在恰当的实际进行释放。
3.游戏开发中的应用
--如下用cocos2dx中的Lua来举例... --2dx经过tolua++把类方法导出 --举例api --按钮响应回调函数格式为: --luaFunc(event) --event为触摸按下,触摸移动,触摸离开等事件 --lua中的API为: --UIButton::addListenHandler(luaFunc) --实际需求是我按钮按下时,我须要改变按钮自身的纹理...此时回调中却没有按钮自己的对象(sender),怎么办呢? --利用闭包就轻松解决了 --下面是LUA实战例子:一个testUI的页面类 local testUI = testUI or {} local testUI:onBtnClick(sender,event) --可获取的参数有:隐藏的self,btn,event end function testUI:initButton() local btn = UIButton:create() --重点来了 btn:addListenHandler( function(event) --使用闭包把self,btn都传进去了.... self:onBtnClick(btn,event) end ) end return testUI
4.lua函数递归以及尾调用消除
1)递归示例:
--反面递归例子(递归必须在初始化之后才能调用) local func = function(n) if n > 0 then return func(n - 1) --此处调用错误 end --正确例子1 local func func = function(n) if n > 0 then return func(n - 1) --此处调用错误 end --正确例子2(此处函数展开后解释为例子1的代码再执行) function func(n) if n > 0 then return func(n - 1) --此处调用错误 end --若是是两个函数嵌套递归(超前递归,必须先声明) local g local f --这里不能加local..否则等于声明了多一个局部变量了,递归的对象就不对了 function g() f() end --这里不能加local..否则等于声明了多一个局部变量了,递归的对象就不对了 function f() g() end
2)尾调用消除(递归的时候若是返回的函数是最后的执行...则不损耗栈空间,至关于GOTO语句)
--尾调用消除 function g() return a,b end --正确例子 function f() return g() --正确的尾调用消除 end --错误例子1 function f(x) return g() + 1 --最后执行的是加法 end --错误例子2 function f(x) return (g()) --最后执行的是强制返回1个值 end --错误例子3 function f(x) return x or g() end
总结:因为LUA尾递归调用这个性质,咱们能够用GOTO来实现状态机了