Lua 函数 类 Table --学习笔记

--[[

Table:

元方法: 当表达式中混合了不同元表的值时, 先看第一个值有无对应元表, 没有再看第二个对象的.

两个对象都没有,应发一个错误. 

算术类的:__add加法, __mul乘法, __sub减法, __div, __unm(相反数), __mod取模, __pow乘幂, __concat连接操作符

关系类的:__eq等于, __lt小于, __le大于, 其他的进行转换:a~=b=>not(a==b), a>b=>b<a, a>=b=>b<=a

库定义的:__tostring, __metatable, 设置__metatable="xxx", getmetatable返回"xxx", setmetatable

引发错误, 起到不能设置元表的保护作用.

关于访问的:

__index: 访问table中不存在的字段时, 没有这个元方法时返回nil, 有的话, 由它返回结果.

__newindex: 当对table中不存在的索引赋值时, 查找它, 调用它而不是赋值, 如是一个table,在此table

中赋值,而不是原来的table.

插入/删除: 一般下标从1开始

table.insert(t,index,v) 指定位置插入元素, 后续元素往后移动

table.insert(t,v) 没有位置参数,添加到数组末尾, 这可以实现  栈--压入

table.remove(t)  栈--弹出

table.insert(t,1,v) 起始处插入, 实现 队列--入队

table.remove(t,1)  从另一端删除(并返回元素), 队列--出队   效率不高,需移动元素

排序: table.sort()

连接: table.concat()

]]--

--[[

函数: 

闭包,闭合函数, Lua可以说没有'函数', 都是closure, 函数是特殊的closure.

closure: 一个函数及访问的非局部变量(upvalue). 没有upvalue就是传统函数

 function newCounter()
     local i = 0  --非局部变量upvalue
     return function() --匿名函数
         i = i + 1
         return i
     end
 end
 c1 = newCounter() --返回一个闭包:匿名函数和它访问的upvalue
 print(c1()) --执行
 print(c1()) --同一个闭包
 c2 = newCounter() --返回另一个闭包环境

沙盒:

 do
     local oldOpen = io.open()
     local accessOK = function(filename, mode)
         --检查权限
     end
     io.open = function(filename, mode) --重新定义
         if accessOK(filename, mode) then  --确保使用安全. 形成沙盒环境
             return oldOpen(filename, mode) --调用原系统库函数
         else
             return nil, "access denied"
         end
     end
 end

尾调用消除:

尾调用: function f(x) return g(x) end --调用完g(x)无事可做. 

消除: 不需要返回f(),不保存它的栈信息, 直接返回调用f的点.  相当于g(x)就是goto的功能.

]]--

--类:

Account = {balance = 0} --balance是公有成员变量
 --new可视为构造函数
 function Account:new(o)
 o = o or {} 
 --将新对象实例的meatatable指向Account
 setmetatable(o,self)
 self.__index = self --Account的__index指向自己
 return o 
 end
 --deposite被视为Account类的公有成员函数
 function Account:deposit(v)
     --这里的self表示对象实例本身
     self.balance = self.balance + v
     --这里得这么理解:local accout = Accout(Accout, {}); accout.deposite(accout,v)
 end
 --下面的代码创建两个Account的对象实例
 --通过Account的new方法构造基于该类的示例对象。
 a = Account:new()
 --[[
 这里需要具体解释一下,此时由于table a中并没有deposite字段,因此需要重定向到Account,
 同时调用Account的deposite方法。在Account.deposite方法中,由于self(a对象)并没有balance
 字段,因此在执行self.balance + v时,也需要重定向访问Account中的balance字段,其缺省值为0。
 在得到计算结果后,再将该结果直接赋值给a.balance。此后a对象就拥有了自己的balance字段和值。
 下次再调用该方法,balance字段的值将完全来自于a对象,而无需在重定向到Account了。
 --]]
 a:deposit(100.00)
 print(a.balance) --输出100
 b = Account:new()
 b:deposit(200.00)
 print(b.balance) --输出200
 
--下面将派生出一个Account的子类,以使客户可以实现透支的功能。
 SpecialAccount = Account:new()  --此时SpecialAccount仍然为Account的一个对象实例
 --SpecialAccount将为Account的子类,下面的方法withdraw可以视为SpecialAccount
 --重写的Account中的withdraw方法,以实现自定义的功能。
 function SpecialAccount:withdraw(v)
     --此时的self将为对象实例。
     if v - self.balance >= self:getLimit() then
         error("Insufficient funds")
     end
     self.balance = self.balance - v
 end


--在执行下面的new方法时,table s的元表已经是SpecialAccount了,而不再是Account。

s = SpecialAccount:new{limit = 1000.00}

--在调用下面的deposit方法时,由于table s和SpecialAccount均未提供该方法,因此访问的仍然是

--Account的deposit方法。

s:deposit(100)



--此时的withdraw方法将不再是Account中的withdraw方法,而是SpecialAccount中的该方法。

--这是因为Lua先在SpecialAccount(即s的元表)中找到了该方法。

s:withdraw(200.00)

print(s.balance) --输出-100


转载于:https://my.oschina.net/SethFeng/blog/300552

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值