Lua注解
@class类声明注解
EmmyLua利用
@class
注解来模拟面向对象中的类,可以继承,可以定义字段/属性
- 完整格式:
--@class MY_TYPE[:PARENT_TYPE] [@comment]
-
应用目标:
- local 变量
- global 变量
-
示例:
---@class Car : Transport @define class Car extends Transport local 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 types local transport = {}
- global 变量
---@type Car @global variable type global_car = {}
- property 属性
local obj = {} ---@type Car @property type obj.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 Car local function setCar(car) ... end ---@param car Car setCallback(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|Ship local function create() ... end ---Here car_or_ship doesn't need @type annotation, EmmyLua has already inferred the type via "create" function local car_or_ship = create() ---@return Car function 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 completion local cls = class()
- 在
@generic 泛型注解
利用
@generic
注解来模拟高级语言中的泛型
- 完整格式:
--@generic T1 [: PARENT_TYPE] [, T2 [: PARENT_TYPE]]
-
应用目标:
- function
-
示例:
---@generic T : Transport, K ---@param param1 T ---@param param2 K ---@return T local function test(param1, param2) -- todo end ---@type Car local car = ... local value = test(car)
@vararg 不定参数注解
使用
@vararg
注解一个函数的不定参数部分的类型
- 完整格式:
---@vararg TYPE
-
示例
---@vararg string ---@return string local 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]