本文针对的读者是有经验的C/C++程序员,希望了解Lua或者迅速抓住Lua的关键概念和模式进行开发的。因此本文并不打算教给读者条件语句的语法或者函数定义的方式等等显而易见的东西,以及一些诸如变量、函数等编程语言的基本概念。本文只打算告诉读者Lua那些与C/C++显著不同的东西以及它们实际上带来了怎样不同于C/C++的思考方式。不要小看它们,它们即将颠覆你传统的C/C++的世界观!
本文一共分初阶、进阶和高阶三大部分,每个部分又有若干章节。读者应当从头至尾循序渐进的阅读,但是标有“*”号的章节(主要讨论OO在Lua中的实现方式)可以略去而不影响对后面内容的理解。读者只要把前两部分完成就可以胜任Lua开发的绝大部分任务。高阶部分可作为选择。
基本类型 | 描述 | 备注 |
---|---|---|
数值(number) | 内部以double表示 | |
字符串(string) | 总是以零结尾,但可以包含任意字符(包括零),因此并不等价于C字符串, 而是其超集 | |
布尔(boolean) | 只有“true”或者“false”两个值。 | |
函数(function) | Lua的关键概念之一。不简单等同于C的函数或函数指针。 | |
表(table) | 异构的Hash表。Lua的关键概念之一。 | |
userdata | 用户(非脚本用户)定义的C数据结构。脚本用户只能使用它,不能定义。 | |
线程(thread) | Lua协作线程(coroutine),与一般操作系统的抢占式线程不一样。 | |
nil | 代表什么也没有,可以与C的NULL作类比,但它不是空指针。 |
function foo(a, b, c, ...) local sum = a + b return sum, c --函数可以返回多个值 end r1, r2 = foo(1, "123", "hello") --平行赋值 print(r1,r2);
输出结果
124hello
函数定义
用关键字function定义函数,以关键字end结束
局部变量
用关键字local定义。如果没有用local定义,即使在函数内部定义的变量也是全局变量
函数可以返回多个值
return a, b, c, …
平行赋值
a,b = c, d
全局变量
前面的代码定义了三个全局变量:foo、r1和r2
local a = {} local b = {x = 1,["hello,"] = "world!"} a["astring"] = "ni,hao!" a[1] = 100 a["a table"] = b for k,v in pairs(a) do print(k,"=>",v); end
输出结果
1=>100 astring=>ni,hao! atable=>table: 0xfd59570
定义表(Table)的方式
a={}, b = {…}
访问表的成员
通过 . 或者 [] 运算符来访问表的成员。
注意:表达式a.b等价于a[b],但不等价于a[b]
表项的键和值
任何类型的变量,除了nil,都可以做为表项的键。从简单的数值、字符串到复杂的函数、表等等都可以;同样,任何类型的变量,除了nil,都可以作为表项的值。给一个表项的值赋nil意味着从表中删除这一项,比如令a.b= nil,则把表a中键为b的项删除。如果访问一个不存在的表项,其值也是nil,比如有c = a.b,但表a中没有键为b的项,则c等于nil。
function create(name,id) local obj = {name = name,id = id} function obj:SetName(name) self.name = name end function obj:GetName() return self.name end function obj:SetId(id) self.id = id end function obj:GetId() return self.id end return obj end local myCreate = create("sam",001) for k,v in pairs(myCreate) do print(k,"=>",v) end print("myCreate's name:",myCreate:GetName(),"myCreate's id:",myCreate.GetId(myCreate)) myCreate:SetId(100) myCreate:SetName("Hello Kity") print("myCreate's name:",myCreate:GetName(),"myCreate's id:",myCreate:GetId())
输出结果
SetName=>function: 0x85efc50 GetId=>function: 0x85efc10 id=>1 SetId=>function: 0x85efd00 GetName=>function: 0x85efce0 name=>sam myCreate’s name:sammyCreate’s id:1 myCreate’s name:Hello KitymyCreate’s id:100
对象工厂模式
如前面代码的create函数
用表来表示对象
把对象的数据和方法都放在一张表内,虽然没有隐藏私有成员,但对于简单脚本来说完全可以接受。
成员方法的定义
function obj:method(a1, a2, …) … end 等价于function obj.method(self, a1, a2, …) … end 等价于obj.method = function (self, a1, a2, …) … end
成员方法的调用
obj:method(a1, a2, …) 等价于obj.method(obj, a1, a2, …)
local function CreateRobot(name, id) local obj = {name = name, id = id} function obj:SetName(name) self.name = name end function obj:GetName() return self.name end function obj:SetId(id) self.id = id end function obj:GetId() return self.id end return obj end local function createFootballRobot(name, id, position) local obj = CreateRobot(name, id) obj.position = "right back" function obj:SetPosition(p) self.position = p end function obj:GetPosition() return self.position end return obj end local mycreateFootballRobot = createFootballRobot("Tom", 1000, "广州") print( "mycreateFootballRobot's name:", mycreateFootballRobot:GetName(), "myCreate's id:", mycreateFootballRobot:GetId(), mycreateFootballRobot:GetPosition() ) mycreateFootballRobot:SetName("麦迪") mycreateFootballRobot:SetId(2000) mycreateFootballRobot:SetPosition("北京") print( "mycreateFootballRobot's name:", mycreateFootballRobot:GetName(), "myCreate's id:", mycreateFootballRobot:GetId(), mycreateFootballRobot:GetPosition() )
输出结果
mycreateFootballRobot’s name:TommyCreate’s id:1000right back mycreateFootballRobot’s name:麦迪myCreate’s id:2000北京
简单、直观
传统、不够动态
参考文献《C/C++程序员的Lua快速入门》