前两天去面试javaweb问到一个问题,在你的项目中有没有用到线程,我特么的一想,这东西不是在c层面的吗,因此说我不了解线程。。。。。javascript
后来回去想啊想啊,我操这特么的不是再问我事物的控制,消息队列的回调?这特么的是什么面试html
下面写出我这两天的答案,另附文章比较长大部分都是引用书本或我的博客java
程序要靠上下文(context)来描述当前作的工做,防止忽略以前的数据,固然咱们学习也要有个铺垫jquery
在此列出以便有些我没有讲到的知识被忽略c++
[多问几个为何]为何匿名内部类中引用的局部变量和参数须要final而成员字段不用?web
lua5.1手册面试
Programming in Luaajax
首先让我想起lua语言中闭包编程
有个疑问:闭包(Closures)内的变量能够保存原值, 那它何时释放掉呢缓存
function newCounter() local i =0; return function() --anonymous function
i = i +1;
return i;
end
end
c1= newCounter();
print(c1());-->1
print(c1());-->2
匿名函数内的i,既不是局部变量,也不是全局变量,i被一个叫upvalue保存,他保存在哪呢,
局部方法,局部变量 ,其实引用的是外部那个local i
lua的变量是垃圾回收的,那个i每调用一次newCounter就会新建一个。
因此那个返回的匿名函数就会绑定到这个新键的i(即upvalue)
其实能够变通的理解,进入了newCounter函数并调用一次i,(并建立了一个新的upvalue i), print(c1()) 和print(c1()) 至关于调用 printnewCount()()) 和print(newCount()())都只进入了newCounter函数一次,并调用匿名函数2次
固然准确得是说是一个闭包,这个闭包的函数体就是i=i+1,因此每次调用一次就至关于把c1
这个闭包中的upvalue + 1,不会再调用newCounter'
学过c++的同窗应该会接触到一个functor
class Counter { public: Counter() : i(0) {} int operator () () { return i++; } int i; };
而后c1=newcounter就至关于
Counter c1;而后c1()就至关于调用了operator,upvalue就至关于上面c++代码中的i
lua和上面的代码的不一样在于,i的生命期是gc维护的
闭包在上下文环境中提供颇有用的功能,这一机制使得咱们能够在 Lua 的函数世界 里组合出奇幻的编程技术。闭包也可用在回调函数中,好比在 GUI 环境中你须要建立一 系列 button,但用户按下 button 时回调函数被调用,可能不一样的按钮被按下时须要处理 的任务有点区别。
更通常的作法是咱们使用匿名函数做为做为参数
技术上来说,闭包指值而不是指函数,函数仅仅是闭包的一个原型声明;尽管如此, 在不会致使混淆的状况下咱们继续使用术语函数代指闭包
从上面咱们能够引出迭代器的概念
迭代器是一种支持指针类型的结构,它能够遍历集合的每个元素。在 Lua 中咱们 经常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素。
给个例子
function list_iter (t) local i = 0 local n = table.getn(t) return function () i = i + 1 if i <= n then return t[i] end end end t = {10, 20, 30} iter = list_iter(t) -- 初始化一个迭代 while true do local element = iter() -- 调用这个迭代 if element == nil then break end print(element) end
--用于for
t = {10, 20, 30}
for element in list_iter(t) do
print(element)
end
范性 for 为迭代循环处理全部的薄记(bookkeeping):首先调用迭代工厂;内部保留 迭代函数,所以咱们不须要 iter 变量;而后在每个新的迭代处调用迭代器函数;当迭 代器返回 nil 时循环结束
迭代器的名字有一些误导,由于它并无迭代,完成迭代功能的是 for 语句,也许是在其余语言好比 java、C++迭代器的说法已经很广泛了, 咱们也将沿用这种术语。
一个完整的迭代器
function allwords (f) -- repeat for each line in the file for l in io.lines() do -- repeat for each word in the line for w in string.gfind(l, "%w+") do -- call the function f(w) end end end --若是咱们想要打印出单词,只须要 allwords(print) --更通常的作法是咱们使用匿名函数做为做为参数,下面的例子打印出单词'hello'出现 的次数: local count = 0 allwords(function (w) if w == "hello" then count = count + 1 end end) print(count) --用 for 结构完成一样的任务: local count = 0 for w in allwords() do if w == "hello" then count = count + 1 end end print(count)
两种风格的写法相差不大,但也有区别:一方面,第二种风格更容易书写和 方面,for 结构更灵活,可使用 break 和 continue 语句;在真正的迭代器风格写法 中 return 语句只是从匿名函数中返回而不是退出循环
lua中不像大型数据语言java、c++你能够控制对象成员变量或 者成员方法是否私有。lua并无定位到大型程序设计,一般是做为大型系统的一部分
例以下面的例子咱们可使用这种方式变相的实现一个私有的数据
设计的基本思想是,每一个对象用两个表来表示:一个描述状态;另外一个描述操做(或者 叫接口)。对象自己经过第二个表来访问,也就是说,经过接口来访问对象。为了不未 受权的访问,表示状态的表中不涉及到操做;表示操做的表也不涉及到状态,取而代之 的是,状态被保存在方法的闭包内。
function newAccount (initialBalance) local self = {balance = initialBalance} local withdraw = function (v) self.balance = self.balance - v end local deposit = function (v) self.balance = self.balance + v end local getBalance = function () return self.balance end return { withdraw = withdraw, deposit = deposit, getBalance = getBalance } end --[[这儿的关键点在于:这 些方法没有使用额外的参数 self,代替的是直接访问 self。由于没有这个额外的参数,我 们不能使用冒号语法来访问这些对象。函数只能像其余函数同样调用:]] acc1 = newAccount(100.00) acc1.withdraw(40.00) print(acc1.getBalance()) --> 60
下面来一个方法私有化的例子
例如,咱们的帐号能够给某些用户取款享有额外的 10%的存款上限,可是咱们不想 用户直接访问这种计算的详细信息,咱们实现以下:
function newAccount (initialBalance) local self = { balance = initialBalance, LIM = 10000.00, } local extra = function () if self.balance > self.LIM then return self.balance*0.10 else return 0 end end local getBalance = function () return self.balance + self.extra() end --------------------------------------------- --[[此段代码并无写完,可是经过上面这段,咱们就能够知道extra方法不会对外部曝光,这样,对于用户而言就没有办法直接访问 extra 函数了。]]
引人深思的单例模式由此而生
,-----------------写到这有了一些深恶痛绝的醒悟,这些与java的匿名内部类有关联吗--------------------------------
不说了,继续写
--[[关于 single-method 的对象一个有趣的状况是:当这个 single-method 实际是一个基于 重要的参数而执行不一样的任务的分派(dispatch)方法时。针对这种对象:]] function newObject (value) return function (action, v) if action == "get" then return value elseif action == "set" then value = v else error("invalid action") end end end --使用起来很简单: d = newObject(0) print(d("get")) --> 0 d("set", 10) print(d("get")) --> 10
这种方式没有继承但有私有性:访问对象状态的惟一方式是经过它的内部方法。
其实上面这段代码,牵扯甚多闭包的应用,这就须要一个coroutine例子来考虑了
先付个连接https://www.zybuluo.com/wsd1/note/623964
-----------------------------------------------------后续----------------------------------------------------------------------------------
下面咱们了解下java中的匿名内部类、内部类都知足什么条件才算是
1,、匿名内部类可使用外部类的变量
二、匿名内部类中不一样的方法能够共享这些变量
三、是引用了自由变量的函数。这个函数一般被定义在另外一个外部函数中,而且引用了外部函数中的变量。
四、返回了可调用的对象,它记录了一些信息,这些信息来自于建立它的做用域。
五、 是一个匿名的代码块,能够接受参数,并返回一个返回值,也能够引用和使用在它周围的,可见域中定义的变量
六、是一个表达式,它具备自由变量及邦定这些变量的上下文环境。
七、闭包容许你将一些行为封装,将它像一个对象同样传来递去,并且它依然可以访问到原来第一次声明时的上下文。
八、 是指拥有多个变量和绑定了这些变量的环境的表达式(一般是一个函数),于是这些变量也是该表达式的一部分。
九、 闭包是能够包含自由(未绑定)变量的代码块;这些变量不是在这个代码块或者任何全局上下文中定义的,而是在定义代码块的环境中定义。
你们都知道闭包的概念在javascript中应用最为普遍,最多的是从一个回调函数来处理用户的异步事件,这些看起来都是很是抽象难以理解,其实你能够了解下jquery中ajax函数的定义,运用回调函数来处理用户的一些事件触发
举一个简单的例子你可能在上面的链接中看到了,适合人思考方式的程序是顺序事务的,好比作个西红柿炒蛋,切西红柿->热油->下锅炒,程序通常写成那样顺序的,最符合直觉。
可是你在定义这个程序的时候不可能不考虑一些开销,这就引出了一个事件,切好西红柿没有油了就得去买,就得悬挂起现场等着。
那么怎么挂起这个现场呢,程序语言对这个问题的不一样解决方法,造成了各类语言不一样的风格。
低级语言,会考虑使用寄存器来实现放进堆保存
高级语言(解释型或虚拟机)也是使用阻塞式和回调式来处理事件等候这个问题
高级语言中回调过程处理现场每每是经过语言特征对状态作缓存处理,用一个比较学术的名词描述,就是“闭包(closure)”。javascript就是这类的典型,来看一个例子
<script type="text/javascript"> function f1() { var n = 99; return function(){
alert(n);
}; } f1(); </script>
f1的局部变量能够经过返回的匿名内部类funcion()调用,
今天先写这些,后续