五邑隱俠,本名關健昌,12年游戲生涯, 本教程以 Unity 3D + VS Code + C# + tolua 為例,
如果你還沒有編程基礎,建議你先學習一些編程基礎,本文不是完全菜鳥教程,主要針對有其他語言經驗的開發者,如果想看菜鳥教程,建議看菜鳥教程的 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 代碼提示,例如將滑鼠放到代碼中出現 BsnsPack 的地方上,會有小彈窗提示這個table的key,以及key的型別,
用得比較多的注解有 ---@class,---@return,---@param
2、第2行,定義一個叫 BsnsPack 的class(通過table模擬),
Lua里沒有類,Lua的結構化資料型別叫table,基于key-value結構,相對于其他語言的 map / dictionary,訪問一個table的key對應的值,可以用點 . 來訪問,也可以用中括號[]來訪問
Lua里沒有單獨的陣列結構,也是基于table,陣列下標是key,陣列元素是value,要注意的是,Lua里陣列下標是從1開始的,
創建table的最簡單方式就是花括號 {},創建一個空table,
Lua是腳本語言,變數不需要指定型別,只需要給它賦值,所以 BsnsPack = {maxSerialNo = 0,} 相當于定義了個變數 BsnsPack,它的值是一個table,
Lua的變數默認是全域的,加載到記憶體的Lua代碼都可以訪問這個變數,為了避免命名沖突和意外修改,一般建議變數定義為區域變數,限制它的作用域,在變數前面加個 local定義區域變數,
這里定義的 BsnsPack ,作用域只在這個檔案里,其他檔案不能訪問,也可以在函式、代碼塊里用 local 定義區域變數,
3、第7行,給 BsnsPack一個叫 __index 的 key 賦值為 BsnsPack 自己
Lua 的 table 里,__index 是個特殊的key,這是 Lua實作類和繼承的關鍵, Lua里有個概念叫做元表,Lua定義了一些語言默認key,這些key一般跟 +、-、*、/等運算子、key的訪問、值更新關聯,這些key叫做元方法(Lua里的函式/方法也可以作為值),這些元方法合起來叫元表,Lua里設定元表的方法是代碼第 21 行的 function setmetatable(t, metatable),呼叫這個方法會讓引數 metatable 成為 引數 t 的元表,
設定元表后,在代碼里訪問引數 t 的一個key時會發生以下情況:
1)Lua先在 t 里找,看有沒有這個key,如果有,就回傳這個key的值,否則,執行2)
2)Lua看引數 metatable 有沒有 __index 這個key,如果有,就在 __index 對應的值里查找(__index的值如果是表,在這個表里查找;如果是函式,執行這個函式)
BsnsPack.__index = BsnsPack,如果其他的table設定 BsnsPack 為元表,就可以訪問 BsnsPack 所有的key, 這些key的值如果是方法,就可以呼叫這些方法, 所以 BsnsPack 可以定義方法的模板,這就跟class類似,BsnsPack定義的資料key,相當于靜態欄位class field,BsnsPack定義的方法key,可以是成員方法member method,也可以是class method,后面介紹4、第11~23行,定義BsnsPack的一個叫new的key,它的值是一個方法
Lua里一個代碼塊不用花括號{},通過end作為結束標記,
定義方法用 function 開頭,用點.或者冒號:分割talbe名和方法名,
用冒號:定義的方法,會有個默認引數self,相當于呼叫者,如果外部用 BsnsPack:new() 這樣呼叫,則self == BsnsPack,如果用a:new()這樣呼叫,self==a,
用點.定義的方法,沒有默認引數,只能顯式寫引數self,
一般地,用冒號:定義成員方法member method(例如第23行的 function BsnsPack:setSerialNo(serialNo) )
1)呼叫 o:setSerialNo(serialNo) 時,這里的self是物件o,只改物件o的serialNo,其他物件的serialNo不受影響,
用點.定義構造物件的方法(例如第11行的 function BsnsPack.new()),以及靜態方法class method(例如第69行的 function BsnsPack.test() )
1)在其他地方通過 BsnsPack.new()構造BsnsPack物件
1)在其他地方通過 BsnsPack.test()呼叫類方法
建議,方法定義的時候是冒號:,呼叫的時候用冒號:,定義的時候是點.,呼叫的時候也用點.
構造方法不一定叫new,只是為了統一,建議都用new,與其他語言一致,
方法new里面的 local o = {},定義的key都是成員欄位member field(每次呼叫方法 BsnsPack.new() 都創建一個新的 table并對其欄位初始化后回傳)
Lua沒有私有的成員方法,可以定義檔案的 local 方法,把物件作為引數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行,通過呼叫BsnsPack構造方法初始化o,o是BsnsPack的物件,擁有基類所有的member field
第97行,定義Response相對于基類新增的欄位code
第99、100行,修改o的元表為Response,這樣o可以訪問Response所有的成員方法 member method(通過遞回,包括BsnsPack所有的成員方法)
Response可以重寫BsnsPack的方法
1 function Response:getPayload() 2 return self.payload 3 end
由于Lua里訪問key,先在table本身查找,如果沒有才在元表查找,所以會呼叫重寫的方法,實作多型,
7、第110~115行,匯出本檔案定義的類,
由于class的定義都是以 local 方式定義的區域變數,外部不能訪問,所以要把它當作檔案的回傳值 return
如果該檔案只匯出一個class,直接return這個區域變數就可以,(例如,如果只匯出BsnsPack,return BsnsPack 就可以)
由于本檔案需要匯出3個class,這里把他們放到一個table里匯出
其他檔案需要訪問這個檔案的class,需要呼叫require方法匯入進來,該方法的引數是路徑(不含后綴.lua),回傳值是這個lua檔案的return值
1 local bsnsPack = require("Assets.Lua.bsns.bsns_pack") 2 local Request = bsnsPack.Request 3 local Response = bsnsPack.Response
8、如果想模塊化管理,把一個模塊所有的類通過一個檔案暴露給其他模塊,可以在這個檔案定義一個區域變數,把這個模塊所有的檔案的類,都通過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 bsns
5、簡單語法介紹
1)Lua里的陳述句不需要分號;結尾
2)Lua常用的基本資料型別有nil、boolean、number、string、function、table
3)獲取陣列長度用 #陣列變數,例如
1 local array = {"Lua", "Tutorial"} 2 local len = #array 3 print(len)
4)遍歷陣列用
1 for i, v in ipairs(table) do 2 3 end
5)遍歷物件用
1 for k, v in pairs(obj) do 2 3 end
6)其他語法請查閱菜鳥教程
6、Lua代碼規范可參考 https://lua.ren/topic/172/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/412993.html
標籤:其他
