Lua注解及代码技巧
Lua注解
@class类声明注解
EmmyLua利用
@class
注解来模拟面向对象中的类,可以继承,可以定义字段/属性
- 完整格式:
--@class MY_TYPE[:PARENT_TYPE] [@comment]
-
应用目标:
- local 变量
- global 变量
-
示例:
---@class Car : Transport @define class Car extends Transportlocal cls = class()function cls:test()end -
示例说明:
将
cls
变量标记为Car
类,在其它地方可以使用@type
注解来标记目标变量类型,以增强代码提示以及其它功能
@type类型标记注解
利用
@type
注解来标记目标变量的类型,以增强代码提示以及其它功能
- 完整格式:
---@type MY_TYPE[|OTHER_TYPE] [@comment]
-
应用目标:
- local 变量
---@type Car|Ship @transport tools, car or ship. Since lua is dynamic-typed, a variable may be of different types---use | to list all possible typeslocal transport = {}- global 变量
---@type Car @global variable typeglobal_car = {}- property 属性
local obj = {}---@type Car @property typeobj.car = getCar()
数组类型
可以利用
MY_TYPE[]
的方式来标注一个数据类型为数组
- 完整格式:
---@type MY_TYPE[]
- 示例:
---@type Car[] local list = {} local car = list[1] -- car. and you'll see completion for i, car in ipairs(list) do -- car. and you'll see completion end
字典类型
可以利用
table<KEY_TYPE, VALUE_TYPE>
的方式来标注一个数据类型为字典
- 完整格式:
---@type table<KEY_TYPE, VALUE_TYPE>
- 示例:
---@type table<string, Car> local dict = {} local car = dict['key'] -- car. and you'll see completion for key, car in pairs(dict) do -- car. and you'll see completion end
函数类型
可以利用
fun(param:MY_TYPE):RETURN_TYPE
的方式来标注一个数据类型为函数
- 完整格式:
---@type fun(param:MY_TYPE):RETURN_TYPE
- 示例:
---@type fun(key:string):Car local carCreatorFn1 local car = carCreatorFn1('key') -- car. and you see code completion ---@type fun():Car[] local carCreatorFn2 for i, car in ipairs(carCreatorFn2()) do -- car. and you see completion end
@alias 别名注解
可以使用
@alias
将一些复杂不容易输入的类型注册为一个新的别名
- 完整格式:
---@alias NEW_NAME TYPE
- 示例
---@alias Handler fun(type: string, data: any):void ---@param handler Handler function addHandler(handler) end
@param参数类型标记注解
利用
@param
注解来标记函数定义参数的类型,以增强代码提示以及其它功能
- 完整格式:
---@param param_name MY_TYPE[|other_type] [@comment]
-
应用目标:
- 函数参数
---@param car Carlocal function setCar(car)...end---@param car CarsetCallback(function(car)...end)- for循环参数
---@param car Car for k, car in ipairs(list) do endc
---@param instID number---@param str string---@param active boolean---@param obj UnityObject---@param point Vector3---@param pName string|boolean---@param onAnimFinishFn fun():void---@param fn fun(GameObject):void---@param fn fun(x:number, y:number):void
@return 函数返回值注解
利用
@return
注解来标记函数的返回值类型
- 完整格式:
---@return MY_TYPE[|OTHER_TYPE] [@comment]
-
应用目标:
- 函数
---@return Car|Shiplocal function create()...end---Here car_or_ship doesn't need @type annotation, EmmyLua has already inferred the type via "create" functionlocal car_or_ship = create()---@return Carfunction factory:create()...end
--- 返回多参数 ---@return number, number, number @costType, costId, priceTotal
@field 属性注解
利用
@field
注解来标记某个类的额外的属性(即使这个属性没有出现在代码里)
- 完整格式:
---@field [public|protected|private] field_name FIELD_TYPE[|OTHER_TYPE] [@comment]
-
应用目标:
- 在
@class
注解之后
---@class Car---@field public name string @add name field to class Car, you'll see it in code completionlocal cls = class() - 在
@generic 泛型注解
利用
@generic
注解来模拟高级语言中的泛型
- 完整格式:
--@generic T1 [: PARENT_TYPE] [, T2 [: PARENT_TYPE]]
-
应用目标:
- function
-
示例:
---@generic T : Transport, K---@param param1 T---@param param2 K---@return Tlocal function test(param1, param2)-- todoend---@type Carlocal car = ...local value = test(car)
@vararg 不定参数注解
使用
@vararg
注解一个函数的不定参数部分的类型
- 完整格式:
---@vararg TYPE
-
示例
---@vararg string---@return stringlocal function format(...)local tbl = { ... } -- inferred as string[]end
@language内嵌语言
可以利用
@language
的方式来标注一段文本为某种代码格式,从而可以显示高亮
- 完整格式:
---@language LANGUAGE_ID
- 示例:
---@language JSON local jsonText = [[{ "name":"Emmy" }]]
@see 引用
可以利用
see
的注解来标注一个引用, 解决隐式调用无法查找到相关引用的问题
---@class Emmy local emmy = {} function emmy:sayHello() end ---@see Emmy#sayHello local function testHello() end
代码技巧
默认值
-- number a = a or 0 -- string a = a or "" -- function a = a or function()end -- table a = a or {} -- boolean a = a == nil and true
多条件分支优化
-- if 优化 local Type_= { None = 0, A = 1, B = 2 } local Handler = { [Type_.None] = function(self, arg, arg2) end, [Type_.A] = function(self, arg, arg2) end, [Type_.B] = function(self, arg, arg2) end, } -- 使用 local arg = 1 local arg2= 2 local type = Type_.A EffectHandler[type](self, arg, arg2)
3R原则(the rules of 3R)是:减量化(reducing),再利用(reusing)和再循环(recycling)
polyline = { { x = 1.1, y = 2.9 }, { x = 1.1, y = 3.7 }, { x = 4.6, y = 5.2 }, ... }
polyline = { x = {1.1, 1.1, 4.6, ...}, y = {2.9, 3.7, 5.2, ...} }
Reusing
如果无法避免创建新对象,我们需要考虑重用旧对象。
local t = {} local aux = {year = nil, month = 6, day = 14} for i = 1970, 2000 do aux.year = i t[i] = os.time(aux) end
枚举
RankType = { SSS = "红", SS = "橙", S = "紫", A = "蓝", B = "绿", C = "白", } RankTypes = { [1] = {RankType.C, RankType.B, RankType.A}, [2] = {RankType.S, RankType.SS, RankType.SSS}, } reward = RankTypes[rewardType]
位运算
浮点数判定
将两个数相减,如果差的绝对值小于一个足够小的数就认为他们相等
减法抽象
两个数字的比较逻辑,可以转换成数字相减,然后用结果当条件去做接下来的处理。
以剪刀石头布为例:
-- Rock Paper Scissor RPSString = { [1] = "剪刀", [2] = "石头", [3] = "布", } RPSRes = { Draw = 'D', Lose = 'L', Win = 'W', } -- 对方数值 - 我方数值 对应的结果映射 RPSResMap = { [-2] = RPSRes.Lose, [-1] = RPSRes.Win, [0] = RPSRes.Draw, [1] = RPSRes.Lose, [2] = RPSRes.Win, } RPSTalk = { [RPSRes.Draw] = "棋逢对手", [RPSRes.Lose] = "棋差一招", [RPSRes.Win] = "棋盛一招", } local random = math.random local hisChoice = random(1, 3) local myChoice = random(1, 3) local res = RPSResMap[hisChoice - myChoice] local resString = RPSTalk[res]
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 我与微信审核的“相爱相杀”看个人小程序副业
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~