概述:
Lua 是一種輕量小巧的腳本語言既忆,用標準 C 語言編寫并以源代碼形式開放擂找,其設計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能定躏。
一、變量
Lua 是動態(tài)類型語言芹敌,變量不要類型定義痊远。Lua 變量就兩種類型:全局變量、局部變量党窜。
使用 local 關鍵字聲明的拗引、在函數(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ù)運算符
- 關系運算符
- 邏輯運算符
- 其他運算符
3.1径簿、算術(shù)運算符
算術(shù)運算符就是加法罢屈、減法、乘法篇亭、乘法缠捌、取余等這些。和 C 語言是一樣的译蒂。
3.2鄙币、關系運算符
關系運算 就是等于、不等于蹂随、大于、大于等于因惭、小于等于岳锁、小于。
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)其實是一個“關聯(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 使用關聯(lián)型數(shù)組涨薪,你可以用任意類型的值來作數(shù)組的索引骑素,但這個值不能是 nil。
Lua table 是不固定大小的刚夺,你可以根據(jù)自己需要進行擴容献丑。
Lua 也是通過 table 來解決模塊(module)、包(package)和對象(Object)的侠姑。
5.1创橄、table 的構(gòu)造
-- 創(chuàng)建一個表
mytable = {}
-- table 里面值的設置和獲取
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 的行為绕娘,每個行為關聯(lián)了對應的元方法。
有兩個很重要的函數(shù)來處理元表:
setmetatable(table,metatable): 對指定 table 設置元表(metatable)栽连,如果元表(metatable)中存在 metatable 鍵值险领,setmetatable 會失敗 侨舆。
getmetatable(table): 返回對象的元表(metatable)。
-- 給指定表設置元表
mytable = {} -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable, mymetatable) -- 把 mymetatable 設為 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