發(fā)布時間:2024-04-08 09:23:19 瀏覽量:149次
如果你還沒有編程基礎,建議你先學習一些編程基礎。本文不是完全菜鳥教程,主要針對有其他語言經(jīng)驗的開發(fā)者,如果想看菜鳥教程,建議看菜鳥教程的 Lua教程。
先看一個簡單類的代碼

1 ---@class BsnsPack @Base class of business pack
2 local BsnsPack = {
3 -- class fields
4 maxSerialNo = 0,
5 }
6
7 BsnsPack.__index = BsnsPack
8
9 --- new()
10 ---@return BsnsPack
11 function BsnsPack.new()
12 local o = {}
13
14 -- member fields
15 o.serialNo = 0
16 o.mod = 0
17 o.cmd = 0
18 o.payload = nil
19
20 -- bind BsnsPack methods
21 setmetatable(o, BsnsPack)
22 return o
23 end
24
25 --- set serial No.
26 ---@param serialNo number
27 function BsnsPack:setSerialNo(serialNo)
28 self.serialNo = serialNo
29 end
30
31 --- get serial No.
32 ---@return number
33 function BsnsPack:getSerialNo()
34 return self.serialNo
35 end
36
37 --- set mod
38 ---@param mod number
39 function BsnsPack:setMod(mod)
40 self.mod = mod
41 end
42
43 --- get mod
44 ---@return number
45 function BsnsPack:getMod()
46 return self.mod
47 end
48
49 --- set cmd
50 ---@param cmd number
51 function BsnsPack:setCmd(cmd)
52 self.cmd = cmd
53 end
54
55 --- get cmd
56 ---@return number
57 function BsnsPack:getCmd()
58 return self.cmd
59 end
60
61 --- set payload
62 ---@param payload any
63 function BsnsPack:setPayload(payload)
64 self.payload = payload
65 end
66
67 --- get payload
68 ---@return any
69 function BsnsPack:getPayload()
70 return self.payload
71 end
72
73 function BsnsPack.test()
74 print(BsnsPack.serialNo)
75 end
76
77 --- testPrivate
78 ---@param self BsnsPack
79 local function testPrivate(self)
80 print(self.serialNo)
81 end
82
83 ---@alias Request BsnsPack @Request is BsnsPack
84 local Request = BsnsPack
85
86 ---@class Response : BsnsPack @Response class
87 local Response = {}
88 setmetatable(Response, BsnsPack) -- bind super methods
89 Response.__index = Response
90
91 --- new()
92 ---@return Response
93 function Response.new()
94 local o = BsnsPack.new()
95
96 -- member fields
97 o.code = 0
98
99 setmetatable(o, nil) -- remove original metatable
100 setmetatable(o, Response) -- bind Response methods
101 return o
102 end
103
104 --- get result code
105 ---@return number
106 function Response:getCode()
107 return self.code
108 end
109
110 local bsnsPack = {}
111 bsnsPack.BsnsPack = BsnsPack
112 bsnsPack.Request = Request
113 bsnsPack.Response = Response
114
115 return bsnsPack
1、第1行:這是一行注釋
Lua的行注釋以兩個減號 -- 開頭,
class注解:---@class TYPE[: PARENT_TYPE {, PARENT_TYPE}] [@comment]
這樣有利于 VS Code 代碼提示,例如將鼠標放到代碼中出現(xiàn) BsnsPack 的地方上,會有小彈窗提示這個table的key,以及key的類型。
用得比較多的注解有 ---@class,---@return,---@param
2、第2行,定義一個叫 BsnsPack 的class(通過table模擬)。
Lua里沒有類,Lua的結(jié)構(gòu)化數(shù)據(jù)類型叫table,基于key-value結(jié)構(gòu)。相對于其他語言的 map / dictionary。訪問一個table的key對應的值,可以用點 . 來訪問,也可以用中括號[]來訪問
Lua里沒有單獨的數(shù)組結(jié)構(gòu),也是基于table,數(shù)組下標是key,數(shù)組元素是value,要注意的是,Lua里數(shù)組下標是從1開始的。
創(chuàng)建table的最簡單方式就是花括號 {},創(chuàng)建一個空table。
Lua是腳本語言,變量不需要指定類型,只需要給它賦值。所以 BsnsPack = {maxSerialNo = 0,} 相當于定義了個變量 BsnsPack,它的值是一個table。
Lua的變量默認是全局的,加載到內(nèi)存的Lua代碼都可以訪問這個變量。為了避免命名沖突和意外修改,一般建議變量定義為局部變量,限制它的作用域。在變量前面加個 local定義局部變量。
這里定義的 BsnsPack ,作用域只在這個文件里。其他文件不能訪問。也可以在函數(shù)、代碼塊里用 local 定義局部變量。
3、第7行,給 BsnsPack一個叫 __index 的 key 賦值為 BsnsPack 自己
Lua 的 table 里,__index 是個特殊的key,這是 Lua實現(xiàn)類和繼承的關(guān)鍵。
Lua里有個概念叫做元表。Lua定義了一些語言默認key,這些key一般跟 +、-、*、/等操作符、key的訪問、值更新關(guān)聯(lián),這些key叫做元方法(Lua里的函數(shù)/方法也可以作為值),這些元方法合起來叫元表。
Lua里設置元表的方法是代碼第 21 行的 function setmetatable(t, metatable),調(diào)用這個方法會讓參數(shù) metatable 成為 參數(shù) t 的元表。
設置元表后,在代碼里訪問參數(shù) t 的一個key時會發(fā)生以下情況:
1)Lua先在 t 里找,看有沒有這個key,如果有,就返回這個key的值。否則,執(zhí)行2)
2)Lua看參數(shù) metatable 有沒有 __index 這個key,如果有,就在 __index 對應的值里查找(__index的值如果是表,在這個表里查找;如果是函數(shù),執(zhí)行這個函數(shù))
BsnsPack.__index = BsnsPack,如果其他的table設置 BsnsPack 為元表,就可以訪問 BsnsPack 所有的key。 這些key的值如果是方法,就可以調(diào)用這些方法。
所以 BsnsPack 可以定義方法的模板,這就跟class類似。BsnsPack定義的數(shù)據(jù)key,相當于靜態(tài)字段class field。BsnsPack定義的方法key,可以是成員方法member method,也可以是class method,后面介紹
4、第11~23行,定義BsnsPack的一個叫new的key,它的值是一個方法
Lua里一個代碼塊不用花括號{},通過end作為結(jié)束標記。
定義方法用 function 開頭,用點.或者冒號:分割talbe名和方法名,
用冒號:定義的方法,會有個默認參數(shù)self,相當于調(diào)用者,如果外部用 BsnsPack:new() 這樣調(diào)用,則self == BsnsPack,如果用a:new()這樣調(diào)用,self==a。
用點.定義的方法,沒有默認參數(shù),只能顯式寫參數(shù)self。
一般地,用冒號:定義成員方法member method(例如第23行的 function BsnsPack:setSerialNo(serialNo) )
1)調(diào)用 o:setSerialNo(serialNo) 時,這里的self是對象o,只改對象o的serialNo,其他對象的serialNo不受影響。
用點.定義構(gòu)造對象的方法(例如第11行的 function BsnsPack.new()),以及靜態(tài)方法class method(例如第69行的 function BsnsPack.test() )
1)在其他地方通過 BsnsPack.new()構(gòu)造BsnsPack對象
1)在其他地方通過 BsnsPack.test()調(diào)用類方法
建議,方法定義的時候是冒號:,調(diào)用的時候用冒號:,定義的時候是點.,調(diào)用的時候也用點.
構(gòu)造方法不一定叫new,只是為了統(tǒng)一,建議都用new,與其他語言一致。
方法new里面的 local o = {},定義的key都是成員字段member field(每次調(diào)用方法 BsnsPack.new() 都創(chuàng)建一個新的 table并對其字段初始化后返回)
Lua沒有私有的成員方法,可以定義文件的 local 方法,把對象作為參數(shù)self顯式的傳進去(例如第79行 local function testPrivate(self))
5、第84行,給類BsnsPack定義一個別名 Request,其實就是把一個table賦值給另外一個變量
6、第87~102行,定義一個類Response,繼承基類BsnsPack
第87行,定義子類Response
第88行,設置元表,使得Response可以訪問BsnsPack所有的key(繼承BsnsPack所有的方法)
第89行,所有對象可以訪問Response所有的key(通過遞歸,包括BsnsPack所有的key)
第94行,通過調(diào)用BsnsPack構(gòu)造方法初始化o,o是BsnsPack的對象,擁有基類所有的member field
第97行,定義Response相對于基類新增的字段code
第99、100行,修改o的元表為Response,這樣o可以訪問Response所有的成員方法 member method(通過遞歸,包括BsnsPack所有的成員方法)
Response可以重寫B(tài)snsPack的方法
1 function Response:getPayload()
2 return self.payload
3 end由于Lua里訪問key,先在table本身查找,如果沒有才在元表查找,所以會調(diào)用重寫的方法,實現(xiàn)多態(tài)。
7、第110~115行,導出本文件定義的類。
由于class的定義都是以 local 方式定義的局部變量,外部不能訪問,所以要把它當作文件的返回值 return
如果該文件只導出一個class,直接return這個局部變量就可以,(例如,如果只導出BsnsPack,return BsnsPack 就可以)
由于本文件需要導出3個class,這里把他們放到一個table里導出
其他文件需要訪問這個文件的class,需要調(diào)用require方法導入進來,該方法的參數(shù)是路徑(不含后綴.lua),返回值是這個lua文件的return值
1 local bsnsPack = require("Assets.Lua.bsns.bsns_pack")
2 local Request = bsnsPack.Request
3 local Response = bsnsPack.Response8、如果想模塊化管理,把一個模塊所有的類通過一個文件暴露給其他模塊,可以在這個文件定義一個局部變量,把這個模塊所有的文件的類,都通過require導入進來,并賦值給跟類同名的key,最后返回這個局部變量
文件bsns.lua
1 local bsns = {}
2
3 local bsnsPack = require("Assets.Lua.bsns.bsns_pack")
4 bsns.Request = bsnsPack.Request
5 bsns.Response = bsnsPack.Response
6
7 bsns.BsnsMod = require("Assets.Lua.bsns.bsns_mod")
8 bsns.BsnsCenter = require("Assets.Lua.bsns.bsns_center")
9
10 return bsns9、可以實現(xiàn)一個通用的類定義函數(shù)
1 --- define a class
2 --- t._className, a string array, define class name
3 --- t._super, a table, define super class
4 --- t.__ctor, a function(self, ...), define member fields
5 --- @param t any
6 function class(t)
7 -- extends super
8 if t._super ~= nil then
9 -- static fields and methods
10 local superStaticClone = {}
11 for k, v in pairs(t._super) do
12 if k == "_ctor" then
13 goto continue
14 end
15
16 superStaticClone[k] = v
17
18 ::continue::
19 end
20
21 setmetatable(t, superStaticClone)
22 end
23
24 t.__index = t
25 -- new method
26 t.new = function(...)
27 local o = {}
28 invokeCtor(o, t, ...)
29
30 setmetatable(o, t) -- bind class
31 return o
32 end
33
34 function invokeCtor(o, cls, ...)
35 if cls._super ~= nil then
36 invokeCtor(o, cls._super, ...)
37 end
38
39 if cls._ctor ~= nil then
40 setmetatable(o, cls)
41 o:_ctor(...)
42 setmetatable(o, nil)
43 end
44 end
45
46 return t
47 end有了這個函數(shù)可以這樣定義類
1 local TestClass = class({
2 -- class name
3 _className = "TestClass",
4
5 -- static fields:
6 size = 2,
7 count = 0,
8
9 -- member:
10 _ctor = function(self, ...)
11 local params = {...}
12 self.count = params[1]
13 self.age = params[2]
14 end
15 })
16
17 local TestClass2 = class({
18 _className = "TestClass2",
19 ---@class TestClass
20 _super = TestClass,
21
22 _ctor = function(self, ...)
23 self.fdsl = 3256
24 end
25 })10、簡單語法介紹
1)Lua里的語句不需要分號;結(jié)尾
2)Lua常用的基本數(shù)據(jù)類型有nil、boolean、number、string、function、table
3)獲取數(shù)組長度用 #數(shù)組變量,例如
1 local array = {"Lua", "Tutorial"}
2 local len = #array
3 print(len)4)遍歷數(shù)組用
1 for i, v in ipairs(table) do
2
3 end5)遍歷對象用
1 for k, v in pairs(obj) do
2
3 end6)其他語法請查閱菜鳥教程
11、Lua代碼規(guī)范可參考
https://lua.ren/topic/172/
熱門資訊
探討游戲引擎的文章,介紹了10款游戲引擎及其代表作品,涵蓋了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戲設計領(lǐng)域和數(shù)字藝術(shù)教育的重要性,歡迎點擊咨詢報名。
2. 手機游戲如何開發(fā)(如何制作傳奇手游,都需要準備些什么?)
?如何制作傳奇手游,都需要準備些什么?提到傳奇手游相信大家都不陌生,他是許多80、90后的回憶;從起初的端游到現(xiàn)在的手游,說明時代在進步游戲在更新,更趨于方便化移動化。而如果我們想要制作一款傳奇手游的
3. B站視頻剪輯軟件「必剪」:免費、炫酷特效,小白必備工具
B站視頻剪輯軟件「必剪」,完全免費、一鍵制作炫酷特效,適合新手小白??靵碓囋?!
游戲中玩家將面臨武俠人生的掙扎抉擇,戰(zhàn)或降?殺或放?每個抉定都將觸發(fā)更多愛恨糾葛的精彩奇遇?!短烀嬗肪哂卸嗑€劇情多結(jié)局,不限主線發(fā)展,高自由...
?三昧動漫對于著名ARPG游戲《巫師》系列,最近CD Projekt 的高層回應并不會推出《巫師4》。因為《巫師》系列在策劃的時候一直定位在“三部曲”的故事框架,所以在游戲的出品上不可能出現(xiàn)《巫師4》
6. 3D動畫軟件你知道幾個?3ds Max、Blender、Maya、Houdini大比拼
當提到3D動畫軟件或動畫工具時,指的是數(shù)字內(nèi)容創(chuàng)建工具。它是用于造型、建模以及繪制3D美術(shù)動畫的軟件程序。但是,在3D動畫軟件中還包含了其他類型的...
想讓你的3D打印模型更堅固?不妨嘗試一下Cura參數(shù)設置和設計技巧,讓你輕松掌握!
8. 虛幻引擎5節(jié)省存儲空間用這招!緩存的清理與設置
眾所周知,虛幻引擎5(下面簡稱UE5)特別占用存儲空間,僅一個版本安裝好的文件就有60G,這還不包括我們在使用時保存的工程文件和隨之產(chǎn)生的緩存文件。而...
9. Bigtime加密游戲經(jīng)濟體系揭秘,不同玩家角色的經(jīng)濟活動
Bigtime加密游戲經(jīng)濟模型分析,探討游戲經(jīng)濟特點,幫助玩家更全面了解這款GameFi產(chǎn)品。
10. 3D動漫建模全過程,不是一般人能學的會的,會的多不是人?
步驟01:面部,頸部,身體在一起這次我不準備設計圖片,我從雕刻進入。這一次,它將是一種純粹關(guān)注建模而非整體繪畫的形式。像往常一樣,我從Sphere創(chuàng)建它...
最新文章
同學您好!