Lua 学习笔记

最近要用到 Lua 编程语言,所以学习了一些简明教程,同时记录一下 Lua 编程语言相对于其他主流编程语言在语法上特殊的地方。其中,在 Lua 中使用Table数据结构实现“面向对象”编程是重点。

注释

-- 单行注释
--[[
块注释,有趣的是这个注释标记不是对称的
--]]

变量

  1. 变量没有类型,值才有类型,也就是在声明变量的时候不需要声明变量的类型。
  2. 数字只有 double 类型 。
  3. 没有定义过的变量值为 nil
  4. 对于布尔类型,只有 nilfalse 表示假,其他的值都为真。
  5. 默认变量都是全局变量,局部变量需要加 local 关键字

操作符

  1. Lua 中没有 +++= 这类的运算符
  2. 不等于号是 ~=
  3. 字符串链接符是 ..
  4. 条件表达的“与”、“或”、“非”分别是and,or,not

控制语句

if-else 分支

i = 10
if i = 0 then
-- do something
elseif i > 5 and i < 10 then
-- do something
else
-- do something 
end

while 循环

i = 0
while i < 100 do
  -- do something
  i = i + 1
end

until 循环

sum = 2
repeat
  sum = sum ^ 2
until sum > 100

for 循环

for i=1, 100, 2 do
-- do something
end

函数

函数可以作为返回值返回

function add(x)
  return function(y) y + x end
end

addOne = add(1)
addOne(1) -- 2

可以返回多个值,同时默认为全局函数。

值得注意的是 Lua 的函数参数不支持默认值,这也为 Lua 程序的重构带来了一些麻烦。

Table

Table 是 Lua 中重要的数据结构,它是由一系列的 key-value 键值对组成。Lua 中的数组也是一种特殊的 Table它下标从 1 开始,而且在一个数组中可以有不同类型的成员。

变量对于 Table 的引用是弱引用,也就是说 Table 是独立于变量存在的,只有当没有任何一个变量引用这个 Table 的时候,Lua 的垃圾回收机制才会把这个 Table 从内存中回收。这个特性对于在 Lua 中实现“面向对象”也很重要。

-- 定义和访问
person = {name = "jack", age =24}
person.name = "black"
person.age = 20

-- 另一种定义和访问
person2 = {['name']="green", ['age']=30}
person2['name'] = "tom"
person2['age'] = 10

-- 数组
arr = {1,2,3,4,5}
arr = {[1]=1,[2]=2,[3]=3,[4]=4,[5]=5} -- 与上面的定义等价

MetaTable 和 MetaMethod

Lua 中每个值都有一套预定义的操作集合,这个集合就是 MateTable ,MetaTable 中预定义的方法就是 MetaMethod。tableuserdata 有各自独立的 MetaTable,从而可以利用这一特性实现“面向对象”编程。而其他类型的值则共享属于该类型的一个 MetaTable。

面向对象

Lua 可以通过使用 Table 这种数据结构来实现面向对象编程。但是这种面向对象并不是基于类(Class)的,而是基于原型(prototype)的。这个原型就是我们定义好的一个 Table,其他对象就可以通过这个原型衍生出来。

定义原型

首先定义一个 Table 当作我们的原型,并定义一个成员变量

Account = { balance = 0 }

这样原型就定义好了,由于 Table 是独立于变量存在的, 只要不把 Account 变量设为 nil ,那么就这个原型就一直存在。在这个原型中有一个 balance 的成员变量。

定义成员方法

紧接上面的代码,我们可以定义一个成员方法

function Account.withdraw(self, v)
  self.balance = self.balance - v
end

其中 Account.withdraw 是一个语法糖, 相当于在 Account 的 Table 中定义了一个 withdraw 的字段,而它的内容就是一个方法,上面的写法等价于:

Account = {
  withdraw = function (self, v)
    self.balance = self.balance - v
  end 
}

在这个方法中使用了 self 关键字,它就是指这个 Table 本身,它有可能是这个原型,也可能是由这个原型衍生出的对象。

同时我们可以在定义成员方法时使用 : 语法糖,默认传入 self 提高编码效率。例如:

function Account:withdraw(v)
 self.balance = self.balance - v
end

生成对象

对象其实也是一个 Table , 只不过这个 Table 并不是空的,而是基于一个原型产生的。基于原型的 Table 就是利用上面的 MetaTable 来实现的。同样基于上面的代码实现一个产生基于 Account 原型的对象的方法new

function Account:new(o)
  if o == nil then
    o = {}
  end
  
  setmetatable(o, self) -- 绑定原型

  self.__index = self --索引原型,方便使用点号

  return o
end

这个方法的关键就是在对象的 MetaTable 中添加了原型 Account。这样当我们要访问对象 o 这个中的某个未定义的字段时,Lua 就会去查找它的 MetaTable 中是否有这个字段,由于我们绑定了原型,这样就能找到原型中的这个字段。比如,我们并没有为 o 定义 withdraw 方法,所以当我们访问 o 的 withdraw 字段时,就会发现 o 本身的 Table 并没有这个字段,然后去查找它的 MetaTable,这样就能访问到原型,也就是 Accountwithdraw 的实现。

派生

由原有的原型派生出新的原型在 Lua 中实现起来也不难,因为原型也是 Table, 我们只要为这个 Table 添加新的字段,或者为原有字段定义新的内容就行了,例如:

SpecialAccount = Account:new{limit = 100}

-- 重新定义 withdraw 方法
function SpecialAccount:withdraw(v)
  if v < self.limit then
    self.balance = self.balance - v
  end
end

在上面的代码中就从 Account 原型中派生出了一个新的原型,其中添加了一个新的limit成员变量和重新定义了withdraw成员方法。

参考资料

  1. LUA简明教程
  2. Lua 5.1 参考手册
  3. Lua 程序设计
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 1.1程序块:Lua执行的每段代码,例如一个源代码文件或者交互模式中输入的一行代码,都称为一个程序块 1.2注释:...
    c_xiaoqiang阅读 2,585评论 0 9
  • 1、loadstring、dofile和loadfile的用法和区别: (1)对loadstring,程序示例如下...
    陈振拥阅读 497评论 0 2
  • lua C api PS:这里是默认我已经学完了lua脚本的基本知识(包括table,元表,函数,基本库, 文件i...
    绿箭ML阅读 3,401评论 0 1
  • 最近项目要用的lua 所以抽空学习 记录一下 IDE有ZeroBrane Studio 我还是用的sublime...
    slimsallen阅读 646评论 3 1
  • 换了一种纸,有点把控不了的感觉!
    夏又幽阅读 172评论 0 0