
概述:
Lua 是一種輕量小巧的腳本語言,用標準 C 語言編寫并以源代碼形式開放,其設(shè)計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能。
一、變量
Lua 是動態(tài)類型語言,變量不要類型定義。Lua 變量就兩種類型:全局變量、局部變量。
使用 local 關(guān)鍵字聲明的、在函數(shù)體內(nèi)的,就是局部變量。其它都是全局變量。
-- test.lua 文件腳本
a = 5 -- 全局變量
local b = 5 -- 局部變量
function funcationName()
c = 5 -- 局部變量
local d = 6 -- 局部變量
end
print(a, b, c, d) -- 打印值為:5 5 nil nil
二、循環(huán)和流程控制語句
2.1、while 循環(huán)
while( true )
do
print("循環(huán)將永遠執(zhí)行下去")
end
--實例
i = 1
while(i < 5)
do
i = i + 1
print(i)
end
2.2、for 循環(huán)
數(shù)值 for 循環(huán):
var 從 exp1 變化到 exp2,每次變化以 exp3 為步長遞增 var,并執(zhí)行一次"執(zhí)行體"。exp3 是可選的,如果不指定,默認為 1。
for var=exp1,exp2,exp3 do
<執(zhí)行體>
end
--實例
for i=1, 10, 1 do
print(i)
end
泛型 for 循環(huán):
i 是數(shù)組索引值,v 是對應索引的數(shù)組元素值。ipairs 是 Lua 提供的一個迭代器函數(shù),用來迭代數(shù)組。
--打印數(shù)組 a 的所有值
for i,v in ipairs(a)
do print(v)
end ?
--實例
array = {
"value1",
"value2",
"value3"
}
for i,v in ipairs(array) do
print(i,v)
end
2.3、repeat...until 循環(huán)
repeat...until 循環(huán)和 C 語言里面的 do...while() 作用是一樣的。
repeat
statements
until( condition )
--實例
i = 1
repeat
i = i + 1
print(i)
until(i > 5)
2.4、if 語句
if 語句:
if(布爾表達式)
then
--[ 在布爾表達式為 true 時執(zhí)行的語句 --]
end
if...else 語句:
if(布爾表達式)
then
--[ 布爾表達式為 true 時執(zhí)行該語句塊 --]
else
--[ 布爾表達式為 false 時執(zhí)行該語句塊 --]
end
三、運算符
Lua 提供了以下幾種運算符類型:
- 算術(shù)運算符
- 關(guān)系運算符
- 邏輯運算符
- 其他運算符
3.1、算術(shù)運算符
算術(shù)運算符就是加法、減法、乘法、乘法、取余等這些。和 C 語言是一樣的。
3.2、關(guān)系運算符
關(guān)系運算 就是等于、不等于、大于、大于等于、小于等于、小于。
3.3、邏輯運算符
- and 邏輯與操作符。
- or 邏輯或操作符。
- not 邏輯非操作符。
a = true
b = true
-- and
if ( a and b )
then
print("a and b - 條件為 true" )
end
-- or
if ( a or b )
then
print("a or b - 條件為 true" )
end
-- not
if ( not( a and b) )
then
print("not( a and b) - 條件為 true" )
else
print("not( a and b) - 條件為 false" )
end
3.4、其他運算符
“..”,連接兩個字符串。
“#”,一元運算符,返回字符串或表的長度。
“~”,相當于 C 中的“!”。
a = "Hello"
b = "World"
if a ~= b then
end
print("連接字符串 a 和 b ", a..b )
print("b 字符串長度 ", #b )
print("字符串 Test 長度 ", #"Test" )
print("Mob 網(wǎng)址長度 ", #"www.mob.com" )
四、基本類型
Lua 中有 8 個基本類型分別為:nil、boolean、 number、string、userdata、function、thread 和 table。
nil 類型。表示一個無效值。
boolean 類型。false 和 true。
number 類型。表示雙精度類型的實浮點數(shù)。
string 類型。字符串由一對雙引號或單引號來表示。
function 類型。由 C 或 Lua 編寫的函數(shù)。
userdata 類型。表示任意存儲在變量中的 C 數(shù)據(jù)結(jié)構(gòu)。
thread 類型。表示執(zhí)行的獨立線路,用于執(zhí)行協(xié)同程序。
table 類型。Lua 中的表(table)其實是一個“關(guān)聯(lián)數(shù)組”(associative arrays),數(shù)組的索引可以是數(shù)字或者字符串。在 Lua 里,table 的創(chuàng)建是通過“構(gòu)造表達式”來完成,最簡單構(gòu)造表達式是{},用來創(chuàng)建一個空表。
其中 nil、boolean、 number、string 這四種類型和其它語言中的類型的使用都是類似的。 function 和 table 這兩種類型,會在本篇后面部分詳細講解,userdata 和 thread 暫時先不講。
五、table 類型
table 是 Lua 的一種數(shù)據(jù)結(jié)構(gòu)用來幫助我們創(chuàng)建不同的數(shù)據(jù)類型,如:數(shù)組、字典等。
Lua table 使用關(guān)聯(lián)型數(shù)組,你可以用任意類型的值來作數(shù)組的索引,但這個值不能是 nil。
Lua table 是不固定大小的,你可以根據(jù)自己需要進行擴容。
Lua 也是通過 table 來解決模塊(module)、包(package)和對象(Object)的。
5.1、table 的構(gòu)造
-- 創(chuàng)建一個表
mytable = {}
-- table 里面值的設(shè)置和獲取
mytable[1] = "元素1"
mytable["er"] = "元素2"
print("mytable 索引為 1 的元素", mytable[1])
print("mytable 索引為 er 的元素", mytable["er"])
5.2、table 模擬數(shù)組
-- 數(shù)組,lua里面的元素是從 1 開始的
array = {
"value1",
"value2",
"value3"
}
-- 數(shù)組里面值得獲取
print(array[1], array[2], array[3])
5.3、table 模擬字典
-- 字典
dictionary = {
key1 = "value1",
key2 = "value2",
key3 = "value3"
}
-- 字典里面值得獲取
print(dictionary.key1, dictionary.key2, dictionary.key3)
六、函數(shù)類型
函數(shù)是對語句和表達式進行抽象的主要方法。
functionName1 = function(i)
print(i)
end
function functionName2(i)
print(i)
end
functionName1(2)
functionName2(2)
和 C 語言相比,Lua 中函數(shù)的幾個不同點:
-- 1、多返回值,多余的返回值會省略,少的補齊 nil
function multreturn()
return 1, 2
end
print(multreturn())
-- 2、可變參數(shù)
function average(...)
result = 0
local arg = {...}
for i,v in ipairs(arg) do
result = result + v
end
print("總共傳入".. #arg.."個數(shù)")
return result/#arg
end
print("平均值為", average(1, 2, 3, 4, 5, 6, 7, 8, 9))
七、模塊
模塊就是使用 table 來實現(xiàn)的,看起來會讓我們和面向?qū)ο笳Z言里面的類有點相似。
Class = {}
-- 定義一個共有的變量
Class.var1 = "初始化 var1 的值"
-- var1 = "初始化 var1 的值"
-- 定義一個私有變量
local var2 = "初始化 var2 的值"
-- 定義一個共有函數(shù) func1
function Class.func1()
print("這是共有函數(shù) func1")
end
-- 定義私有函數(shù),該函數(shù)只能在本模塊里面使用
local function func2()
print("這是私有函數(shù) func2")
end
-- 定義一個全局函數(shù),可以直接其它模塊里面調(diào)用,但是不能通過該模塊去調(diào)用。
function func3()
print("這是全局函數(shù) func3")
end
return Class
它里面整一個就是一個表,在里面可以定義私有、共有變量,私有、共有函數(shù)。這些特性都是通過表來限制的,如果不是通過表來限制,那這些函數(shù)和變量的作用域都是全局的。
-- 通過require() 函數(shù)導入模塊
local m = require('Module')
print("模塊類型為:", type(m))
-- 修改模塊共有變量
m.var1 = "修改一下 var1"
print("模塊變量值為:", m.var1)
-- 調(diào)用模塊共有函數(shù)
print("模塊func1函數(shù)的調(diào)用:", m.func1())
-- 模塊的加載過程
print("func3 函數(shù)是不是在這里打???", func3())
八、閉包
閉包是函數(shù)中的函數(shù),可以包含父函數(shù)的局部變量的代碼塊,可以始終讓局部變量的值始終保持在內(nèi)存中。
它的最大用處有兩個,一個是可以讀取函數(shù)內(nèi)部的變量,另一個就是讓這些變量的值始終保持在內(nèi)存中。
-- 示例1
function func1()
local x = 0
function ee()
x = x + 1
print(x)
end
return ee
end
local f1 = func1()
for i=1, 5 do
f1()
end
-- 示例2
function func2()
local x = 0
return function()
x = x + 1
print(x)
end
end
local f2 = func2()
for i=1, 5 do
f2()
end
-- 示例3
function func3(a)
local x = a
return function()
x = x + 1
print(x)
end
end
local f31 = func3(3)
for i=1, 5 do
f31()
end
local f32 = func3(10)
for i=1, 5 do
f32()
end
九、元表及元方法
在 Lua table 中我們可以訪問對應的 key 來得到 value 值,但是卻無法對兩個 table 進行操作。
因此 Lua 提供了元表(Metatable),允許我們改變 table 的行為,每個行為關(guān)聯(lián)了對應的元方法。
有兩個很重要的函數(shù)來處理元表:
setmetatable(table,metatable): 對指定 table 設(shè)置元表(metatable),如果元表(metatable)中存在 metatable 鍵值,setmetatable 會失敗 。
getmetatable(table): 返回對象的元表(metatable)。
-- 給指定表設(shè)置元表
mytable = {} -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable, mymetatable) -- 把 mymetatable 設(shè)為 mytable 的元表
-- 返回對象元表
getmetatable(mytable) -- 這回返回mymetatable
__index 元方法
__index 元方法是 metatable 里面最常見的鍵。
當你通過鍵來訪問 table 的時候,如果這個鍵沒有值,那么 Lua 就會尋找該 table 的 metatable(假定有 metatable)中的 __index 鍵。如果 __index 包含一個表格,Lua 會在表格中查找相應的鍵。
-- 實例1
mytable = {
key1 = "value1"
}
mymetatable = {
__index = {
key2 = "metatablevalue"
}
}
setmetatable(mytable, mymetatable)
print(mytable.key1, mytable.key2, mytable.key3)
-- 實例2
mytable = {
key1 = "value1"
}
mymetatable = {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return nil
end
end
}
setmetatable(mytable, mymetatable)
print(mytable.key1, mytable.key2, mytable.key3)
總結(jié):
Lua 查找一個表元素時的規(guī)則,其實就是如下 3 個步驟:
- 在表中查找,如果找到,返回該元素,找不到則繼續(xù)
判斷該表是否有元表,如果沒有元表,返回 nil,有元表則繼續(xù)。
判斷元表有沒有
__index方法,如果__index方法為 nil,則返回 nil;如果__index方法是一個表,則重復 1、2、3;如果__index方法是一個函數(shù),則返回該函數(shù)的返回值。
十、面向?qū)ο笾庋b
面向?qū)ο蟮奶卣饔蟹庋b、繼承、多態(tài)。Lua 是一門弱類型的語言,多態(tài)那肯定是不存在的。
通過元表和元方法以及模塊來模擬類的封裝,請看如下示例:
local User = {}
User.id = 0
User.name = ""
User.age = 0
-- function User:new()
-- print("User 被構(gòu)造了")
-- mytable = {}
-- setmetatable(mytable, self)
-- self.__index = self
-- return mytable
-- end
function User:new(id, name, age)
print("new self:", self)
-- print("User 被構(gòu)造了,", id, name, age)
mytable = {"haha"}
setmetatable(mytable, self)
self.__index = self
self.id = id
self.name = name
self.age = age
return mytable
end
function User:fun()
-- print("fun 成員方法調(diào)用了")
end
function User:setName(name)
print("setName self:", self)
self.name = name
end
function User:getName()
print("getName self:", self)
return self.name
end
return User