lua

语法

只记录重点内容,还有和编程语言在常规使用上的不同之处

变量

类型

Lua 变量有三种类型:全局变量、局部变量、表中的域。

Lua 中的变量全是全局变量,哪怕是语句块或是函数里,除非用 local 显式声明为局部变量。

局部变量的作用域为从声明位置开始到所在语句块结束。

变量的默认值均为 nil。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- test.lua 文件脚本
a = 5 -- 全局变量
local b = 5 -- 局部变量

function joke()
c = 5 -- 全局变量
local d = 6 -- 局部变量
end

joke()
print(c,d) --> 5 nil

do
local a = 6 -- 局部变量
b = 6 -- 对局部变量重新赋值
print(a,b); --> 6 6
end

print(a,b) --> 5 6

应该尽可能的使用局部变量,有两个好处:

    1. 避免命名冲突。
    1. 访问局部变量的速度比全局变量更快。

空、NULL,null

在默认情况下,变量总是认为是全局的。

全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil

1
2
3
4
5
6
> print(b)
nil
> b=10
> print(b)
10
>

如果想删除一个全局变量,只需要将变量赋值为nil。

空判断

nil 作比较时应该加上双引号 “:

1
2
3
4
5
6
7
> type(X)
nil
> type(X)==nil
false
> type(X)=="nil"
true
>

type(X)==nil 结果为 false 的原因是 type(X) 实质是返回的 “nil” 字符串,是一个 string 类型:

1
type(type(X))==string

boolean

boolean 类型只有两个可选值:true(真) 和 false(假),Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true:

与之不同的是,在编程语言,例如,C++和C#中,0是false

String

字符串拼接不使用 加号

相反,由 两个英文句号替代

1
2
3
4
5
> print("a" .. 'b')
ab
> print(157 .. 428)
157428
>

加号字符串的运算中有,有着另外的作用

在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字

1
2
3
4
> print("2" + 6)
8.0
> print("2" + "6")
8.0

索引

索引头

lua做出了一个违背祖宗的决定

不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始。

不过是默认是,这个是可以自行指定的,

1
2
3
4
5
6
7
8
9
array = {}

for i= -2, 2 do
array[i] = i *2
end

for i = -2,2 do
print(array[i])
end

Table是ua中的特殊类型

方括号调用

table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil。

对 table 的索引使用方括号 []。Lua 也提供了 . 操作。

1
2
3
t[i]
t.i -- 当索引为字符串类型时的一种简化写法
gettable_event(t,i) -- 采用索引访问本质上是一个类似这样的函数调用

循环

break 语句 退出当前循环或语句,并开始脚本执行紧接着的语句。
goto 语句 将程序的控制点转移到一个标签处。

遗憾的是lua没有continue操作

面向对象

设置继承的关键在setmetatable和self.__index = self中

Table需要被声明后才能使用

同时对于方法的调用,需要通过实例加上英文的冒号 : ,来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
-- Meta class
Shape = {area = 0}
-- 基础类方法 new
function Shape:new (side)
o = {}
--对于继承的调用来说,首先使用的就是父类的中的方法和属性,因此o在前,将self设置为元表就是让在基础table找不属性和方法的时再去调用元组中的内容
setmetatable(o, self)

-- 这一行设置了 Shape 表的 __index 元方法。这意味着,当Lua查找一个键(属性或方法)在一个对象中不存在时,它会使用 Shape 表本身作为查找的起点
--即从本社找不到后指定去元表中查找
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- 基础类方法 printArea
function Shape:printArea ()
print("面积为 ",self.area)
end

myShapeIns = Shape:new(3)
myShapeIns:printArea()

--table需要首先被声明后才能使用
Square = Shape:new()

function Square:new(side)
o = Shape:new(side)
setmetatable(o,self)
self.__index = self
return o
end

local mySquareIns = Square:new(4)
mySquareIns:printArea()

模块

模块类似于一个封装库,从 Lua 5.1 开始,Lua 加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。

Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行。以下为创建自定义模块 module.lua,文件代码格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}

-- 定义一个常量
module.constant = "这是一个常量"

-- 定义一个函数
function module.func1()
io.write("这是一个公有函数!\n")
end

local function func2()
print("这是一个私有函数!")
end

function module.func3()
func2()
end

return module

自定义测试

名字叫做module的lua文件

1
2
3
4
5
6
7
8
9
module = {}

const = "测试内容"

function module.GetData()
return const
end

return module
1
2
3
module1 =  require("module") --可以自定义名称

print(module1.GetData())