local function main()
local msg = 'Hello Lua!'
print(msg)
end
main()
lua中的字母均为ascii编码而非Unicode编码
标识符需要满足以下三点要求:
区分大小写;
标识符首字符可以为下划线(_)、美元符($)、或者字母开始;
标识符中其他字符可以是下划线(_)、美元符($)、字母或者数字组成
语言中定义具有特殊含义的标识符,保留字不能作为标识符使用
包括:
and,break,do,else,elseif,end,false,for,function,if,in,local,nil,not,or,repeat,return,then,true,until,while
Lua中常量和变量没有区别,通常在命名规范中要求大写常量标识符
eg:
NUM=100
Lua 中的变量全是全局变量,无论语句块或是函数里,除非用 local 显式声明为局部变量,变量默认值均为nil
使用local关键字修饰的变量是局部变量,作用范围为变量声明所在的代码块(一个控制结构内、函数内、文件内或文件串内)
score = 0.0 -- 没有local关键字修饰,为全局变量
local score = 0.0 -- local关键字修饰,为局部变量
local score -- 变量未赋予初始值,默认值为nil,下同
score
单行注释,使用 –
多行注释,使用 --[[ --]]
-- 单行注释
--[[
多行注释1
多行注释2
--]]
包含整数和浮点数
整数:十进制和十六进制(以0x开始)
浮点数:必须包含一个数字、一个小数点或e(或E),如3.14159,-3.1E12,0.1e12
只有true(为真)和false(为假)两个值
若干个封装在双引号(")或单引号(’)内的字符,如"fish",“a line”
在lua中可以通过自定义类型与C进行交互,通过自定义类型可以将任意的C语言数据存储在Lua变量中,代码交互
在lua中函数可以作为一种数据类型使用,函数可以赋值给一个变量,也可以作为参数传递给其他函数
表示一个线程,线程可以通过执行多个,每个线程拥有自己独自的栈、局部变量和指令指针
表类型实现了一组关联数据类型,用{}表示
local point = {x = 10, y = 20}
print(point["x"]) -- 通过下标方式访问
print(point.y) -- 通过字典方式访问
表类型table内可以存放各种类型的变量(包括函数、表等),这也是lua实现面向对象的基础
仅仅只有nil属于该类,表示无效值(在条件表达式中相当于false)
type函数可以返回变量或者数值的类型(得到的是字符串)
type("Hello Lua") -- string
type(100) -- number
type(100.0) -- number
type(true) -- boolean
type(print) -- function
type(nil) -- nil
type({x = 10, y = 20}) -- table
-- 比较类型时需要加上"",因为type得到的是字符串
if type(nil) == "nil" then
-- do something
end
tostring() 可以将bool类型和数值类型转换成字符串类型
tonumber() 可以将非数字的原始值转换成数字
local num = tonumber("AF", 16) -- 返回十六进制数字175
local num = tonumber("0xA") -- 返回10
local num = tonumber(true) -- 返回nil
-- tonumber函数有两个参数,第二个参数是基数(进制),默认基数为十进制
local tb = tonumber({x = 10, y = 20})
print(tostring(tb)) -- 输出nil
运算符 | 作用 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余 |
^ | 幂 |
== | 等于(可以比较不同类型) |
~= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
and | 逻辑与 |
or | 逻辑或 |
not | 逻辑非 |
算术运算符对整数和浮点数都有效
res = 17.6 % 7 -- 3.6
运算优先级(从上到下,由高到低)
优先级 | 运算符 |
---|---|
1 | ^ |
2 | * / |
3 | + - |
4 | < > <= >= ~= == |
5 | and |
6 | or |
if 条件表达式 then
语句组
end
if 条件表达式 then
语句组1
elseif 条件表达式 then
语句组2
.
.
.
else
语句组n
end
通常结构如下:
先判断后执行
[initialization]
while termination do -- termination为true则执行body
body
[iteration] -- 迭代语句,用于改变变量
end
通常结构如下:
先执行后判断
[initialization]
repeat
body
[iteration]
until termination -- 为true则终止循环体
通常结构如下
for var = exp1, exp2, exp3 do
body
end
--[[
* var循环变量从exp1开始,到exp2的值为止,步长为exp3(exp3可省略,默认为1)
* 大于等于exp1,小于等于exp2,则执行循环体
--]]
也可以使用for-in结构
for i,v in ipairs(a) do -- a为数组,ipairs从a中取出循环变量i和元素v
body
end
break语句 用于跳出循环结构
return语句 用于函数返回
return expression -- 返回参数
return -- 无参返回
表类型使用{}创建和初始化,{}表示方式称为table的构造器(constructor)
Student1 = {id = "100", name = "Tony", age = 18}
Student2 = {["id"] = "100", ["name"] = "Tony", ["age"] = 18}
print("Student1 ID:"..Student1["id"])
print("Student2 ID:"..Student2.id)
用两种创建和访问方式均可
数组结构是一种特殊的table结构,同样用{}创建,在创建时没有键,只有值,键默认以数字从1开始排列
local studentList = {"张三", "李四", "王五"}
--[[
1:张三
2:李四
3:王五
--]]
for i,v in ipairs(studentList) do -- ipairs只能用于数组,不能用于字典
print(i..":"..v)
end
for k,v in pairs(studentList) do -- pairs从字典中取出键值对,对于数组同样适用
print(k..":"..v)
end
for i=1, #studentList do -- #获取数组长度,同样典型for循环不能用于字典
print(i..":"..studentList[i])
end
用双引号或单引号括起来表示字符串
lcoal s1 = "Hello 'Lua'!"
local s2 = 'Hello "Lua"!'
单引号内可以使用双引号,双引号内可以使用单引号
使用两点表示字符串拼接
local s = "Hello".."Lua"
string.sub(s,n,m)函数,截取字符串s的第n到第m个字符之间的字符串
local s = "Hello Lua"
local sub1 = string.sub(s, 1, 3) -- "Hel"
local sub2 = string.sub(s, 2, -2) -- "ello Lu"
-1表示最后一个字符,-2表示倒数第二个字符…
string.lower(s) -- 小写
string.upper(s) -- 大写
string.rep("Hello", 3) -- 重复3次,得到HelloHelloHello
string.reverse("Hello") -- 翻转,olleH
string.find(s,sub) -- 从s字符串中查找sub字符串
local s = "Hello Lua"
local i,j = string.find(s, "Hello") -- 返回值有两个,i为开始位置,j为结束位置
类似于C语言中printf的占位符
string.format(“format”, …)进行格式化输出
local s = string.format("%d",10) – s为"10"
function 函数名(参数列表)
语句组
[return 返回值]
end
Lua函数可以定义多重返回值
eg:
function func(a, b)
return a + b, a - b
end
local c, d = func(1,2)
Lua函数内还可以定义函数,默认情况下,嵌套函数的作用域在外函数体内(相当于默认local修饰)
eg:
function calculate(opr, a, b)
function add(a,b)
return a + b
end
function sub(a,b)
return a - b
end
if opr == '+' then
add(a,b)
elseif opr == '-' then
sub(a,b)
end
end
可以将函数作为另一个函数的返回类型使用
function func()
function func2()
-- do somethind
end
return func2()
end
local func3 = func()
func3()
函数可以不定义函数名
function func()
returnfunc = function()
-- do something
end
return returnfunc
end
Lua中不能定义类,但能通过table类型实现面向对象的功能(将table类型变量当做对象)
Student = {id = 100, name = "Tony"}
function Student.toString()
return "Name:"..Student.name.." id:"..Student.id
end
print(Student.toString())
这里的Student为一个对象,toString()函数只属于Student对象
Lua中可以使用self表示自身对象,并通过:调用函数
function Student:toString()
return "Name:"..self.name.." id:"..self.id
end
print(Student:toString())
冒号(:)和点(.)的区别:
*通过冒号定义的方法还是能通过点来进行调用的,同样,通过点定义的方法也是可以使用冒号来调用的。但是,要注意函数输入参数以及函数内是否使用了self(如果用点调用了由冒号定义的函数,且函数内使用了self,则self会为nil,从而出错)
类是对象的模板,通过Student对象作为原型,用来创建其他对象,则可以将Student原型称之为类了
function Student:create(o)
o = o or {}
setmetatable(o, self) -- 将self作为元表设置给o对象
self.__index = self -- 表示首先在当前对象中查找操作,如果当前对象中没有相应操作,就会到原型Student中查找操作
return o
end
local stu = Student:create({id=200, name = "Tom"}) -- 以Student为模板,创建了一个对象
print(stu:toString())
metatable是table中预定义的一系列操作
Lua中的每一个值都有或者可以有一个元表,但table和userdata可以拥有独立的元表,其他类型的值就只能共享其类型所属的元表
Lua在新建table时不会创建metatable,需要使用setmetatable来设置元表
print(getmetatable(a)) -- 查看一个变量的元表,nil表示没有元表
通过设置元表的元方法来进行对元表的设置,最常用的键为__index和__newindex
这是metatable最常用的键
当通过键访问table时,如果该键没有值,那么Lua就会寻找该table的metatable中的__index
eg:
Window = {}
Window.mt = {}
Window.prototype = {x = 0, y = 0, width = 100, height = 100}
Window.mt.__index = function(table, key)
return Window.prototype[key]
end
function Window.new(t)
setmetatable(t, Window.mt)
return t
end
w = Window.new({x = 10, y =20})
print(w.x) -- 10,w中包含x变量,不读取Window中的值0
print(w.width) -- 100,w中不包含width变量,调用元表的__index(这里的__index为函数),调用函数后返回Window中的width的值100
当给一个table一个缺少的索引赋值,解释器就会查找__newindex元方法:如果存在则调用这个函数而不进行赋值操作
eg:
Window.mt.__newindex = function(table, key, value)
print("update of element"..tostring(key)..tostring(value))
rawset(table, key, value)
end
利用metatable实现面向对象的三大特征:封装、继承、多态
People = {age = 18}
function People:new()
local p = {}
setmetatable(p, self)
self.__index = self
return p
end
function People:growUp()
self.age = self.age + 1
print("People's grow up: "..self.age)
end
Man = People:new()
function Man:growUp()
self.age = self.age + 1
print("Man's grow up: "..self.age)
end
man = Man:new()
man:growUp() -- Man's grow up
person = People:new()
person:growUp() -- People's grow up
person = Man:new()
person:growUp() -- Man's grow up