2024年最全lua学习笔记_lua goto(2),个人开发者做一款App需要知道的事情

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

a=nil
print(a and b) --如果a为假,则返回a
print(“\n”)

local c,d=1,false
print( c and d) --如果c为真,则返回d
c=nil
print(c and d) --如果c为假,则返回c
print(“\n”)

local e,f=1,false
print(e or f) --如果e为真,则返回e
e=nil
print(e or f) --如果e为假,则返回f
print(“\n”)

local g,h=1,2
–print(g not h) --错误写法
print(not g) --如果e为真,则返回假
print(not h) --如果h为真,则返回假

local i= false
print(not i) --如果i为假,则返回真
print(“\n”)

–用逻辑运算符or设置值
function func1(a,b)
a= a or b
b= a or b
print(a,b)
end

func1()
func1(10,20)
print(“\n”)

–实现三目运算符 a=b?c:d 如果b=a为真,则值就是c,否则为d
local x,y,z=1,2,3
local u=(x and y) or z
print(u)

x=false
u=(x and y) or z
print(u)
print(“\n”)

local A,B,C=1,2,3
B=false
local D=(A and B) or C
print(D)

local E=((A and {B}) or {C})[1] --这里才是一个合格的三目运算符
print(E)


输出结果:



2
nil

false
nil

1
false

false
false
true

nil nil
10 10

2
3

3
false
PS D:\lua代码>


## 9、流程控制 - 判断



–[[

流程控制语句–判断
if condition then

end
]]–



local a,b=1,2
if(a==1) then
print(a)
else
print(b)
end

if a>=1 then
print(b)
else
print(a)
end

if a<1 then
print(“a<1”)
else
print(“a>b”)
end

local grade,score=60,90
if grade>=60 then
print(“well”)
elseif grade<60 then
print(“fail”)
elseif grade>60 and grade>=90 then
print(“good”)
end

grade,score=60,90
if grade>60 then
print(“well”)
elseif grade<60 then
print(“fail”)
elseif grade>=60 and score>=90 then
print(“good”)
end

if grade< 60 then
print(“fail”)
elseif grade>=65 and grade<70 then
print(“well”)
else
if score>=90 then
print(“good”)
end
end


输出结果:



1
2
a>b
well
good
good
PS D:\lua代码>


## 10、流程控制循环(一) ->while和repeat



–[[

流程控制语句 循环

while condition do
statements
end

没有continue

break只能跳出一次循环,跳出当前while循环语句

goto FLAG 语句跳转到指定标记FLAG处,也可以用于跳出循环,FLAG是一个标记位,相当于一个锚点

两者区别是
break 只能跳出当前循环,而goto 可以跳转到指定位置,这样可以忽略一些代码

在lua 中,没有这些运算符 i++, i–, ++i, --i, +=, -=

a=b=1,lua中这种写法是错误的写法

repeat
–statements
until condition

while 和 repeat的区
while循环中当条件不成立跳出循环
repeat当条件成立时跳出循环
]]–



–求和1+…+100
–local i,sum=nil,nil
local i,sum=0,0
while i<100 do
i=i+1
sum=sum+i
end
print(i,sum)

i,sum=0,0
while i<100 do
if i>49 then
break
end
i=i+1
sum=sum+i
end
print(i,sum)

i,sum=0,0
while i<100 do
if i>49 then
–break
goto FLAG
end
i=i+1
sum=sum+i
end

print(i,sum)

::FLAG::
print(“lua”)

i,sum=0,0
repeat
i=i+1
sum=sum+i
until i>=100

print(i,sum)


输出结果:



100 5050
50 1275
lua
100 5050
PS D:\lua代码>


## 11、流程控制循环goto语句



–[[

流程控制语句

goto FLAG 语句,跳转到指定标记处,也可以用于跳出循环,FLAG是一个标记位,相当于一个锚点
{
int a;
}
代码块,作用域{}
do

end

flag不可见原则
1、不能从外面goto到代码块里面,因为代码块里面的flag对于外面的goto语句来说是不可见的
2、不能跳出或者跳入一个函数,因为函数也是一个block块
3、不能跳入本地变量(local)作用域
]]–

–死循环
– local i=0
– ::FLAG10::
– print(i)
– i=i+1
– goto FLAG10



print(1234)
goto FLAG13
–goto FLAG11 --err 标签FLAG11不可见
–goto FLAG13 --err 标签FLAG12不可见
do
print(“a”)
print(“b”)
::FLAG11::
print(“c”)
print(“d”)
::FLAG12::
end

::FLAG13::
print(“aa”)
print(“bb”)
print(“cc”)
::FLAG14::
print(“dd”)
print(“\n”)

function func1()
::FLAG3::
print( “func1-11”)
print( “func1–22”)
–goto FLAG6 err 标签FLAG6不可见
goto FLAG5
::FLAG4::

print("func1--33")
::FLAG5::

end

– goto FLAG3 err 标签FLAG3不可见
::FLAG6::
print(“aaaa”)
func1()
– goto FLAG4 --FLAG4 err 标签FLAG3不可见
::FLAG7::
print(“bbbb”)

do
a=123
::FLAG1::
–print(a)
::FLAG2::
–goto FLAG3 --此处goto是在local b的作用域外面,使用报错
local b=456
::FLAG3::
–print(b)
goto FLAG3 --此处goto是在local b的作用域里面
end
–print(a)
–print(b)


输出结果:



1234
aa
bb
cc
dd

aaaa
func1-11
func1–22
bbbb


## 12、流程控制循环(二) ->数值for和范围for ipairs



–[[
流程控制语句

for循环分为数值循环和泛型循环(类似foreach)

数值循环
for 变量名=初始值,结束值,步长(默认为1,可以省略) do

end

泛型循环
for k,v in 迭代函数(table) do --此处v可以省略,k不能省略

end

迭代函数 pairs(table) ipairs(table)

ipairts(table) 顺序遍历,中间的序号会断开,遇到 k==v 直接跳过
,遇到第一个nil会终止遍历,一般情况下,ipairs(table)用于数组
类型的集合遍历
]]–



for i=1,10 do
io.write(i," “)
end
print(”\n")

for i=1,10,2 do
io.write(i," “)
end
print(”\n")

for i=1,10,3 do
io.write(i," “)
end
print(”\n")

for i=10,1,-2 do
io.write(i," “)
end
print(”\n")

local tab1={
11,
22,
33,
44,
55
}
for i=1,#tab1 do
io.write(tab1[i]," “)
end
io.write(”\n")

for i=1,10 do
print(tab1[i])
end
io.write(“\n”)

tab2={
11,
22,
“xxx”,
44,
[“key”]=vvv,
“nil”,
key2=“vvv”,
nil,
55
}
for k,v in ipairs(tab2) do
print(k,v)
end

– for k,v in ipairs(tab2) do
– tab2[k]=v*10
– end
for k,v in ipairs(tab2) do
print(k,v)
end


输出结果:



1 2 3 4 5 6 7 8 9 10

1 3 5 7 9

1 4 7 10

10 8 6 4 2

11 22 33 44 55
11
22
33
44
55
nil
nil
nil
nil
nil

1 11
2 22
3 xxx
4 44
5 nil
1 11
2 22
3 xxx
4 44
5 nil
PS D:\lua代码>


## 13、流程控制循环(三) -> pairs



–[[
流程控制语句

for循环分为数值循环和泛型循环(类似foreach)

数值循环
for 变量名=初始值,结束值,步长(默认为1,可以省略) do
    ...
end

泛型循环
for k,v in 迭代函数(table) do  --此处v可以省略,k不能省略
    ...
end

迭代函数 pairs(table) ipairs(table)

ipairts(table) 顺序遍历,中间的序号会断开,遇到 k==v 直接跳过
,遇到第一个nil会终止遍历,一般情况下,ipairs(table)用于数组
类型的集合遍历,而且遍历的是数组下标从1开始不能是负数下标,
如果是负数下标的话跳过负数下标

pairs(tbale) 遇到nil会跳过,同时适用于数组类型和 k==v 类型的集合,
混搭没有问题,如果是混搭的时候,会优先获取数组类型数据

paris的适用范围大于ipairs,类似iparis是pairs的子集
如果使用时不确定选择哪个,无脑pairs

]]–



local tab1={
11,
nil,
“abc”,
22,
“lua”,
33,
44,
55
}

for k,v in pairs(tab1) do
print(k,v)
end
print(“\n”)

local tab2={
11,
id=123,
22,
name=“tom”,
age=456,
33,
conuty=“china”,
nil,
“abc”,
44,
[“province”]=“shanghai”,
55
}
for k,v in pairs(tab2) do
print(k,v)
end

for i=1,9 do
for j=1,i do
io.write(i,“*”,j,“=”,i*j,“\t”)
end
print(“\n”)
end


输出结果:



1 11
3 abc
4 22
5 lua
6 33
7 44
8 55

1 11
2 22
3 33
5 abc
6 44
7 55
conuty china
name tom
province shanghai
id 123
age 456
1*1=1

2*1=2 2*2=4

3*1=3 3*2=6 3*3=9

4*1=4 4*2=8 4*3=12 4*4=16

5*1=5 5*2=10 5*3=15 5*4=20 5*5=25

6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36

7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49

8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64

9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

PS D:\lua代码>


## 14、table -> array



–[[
table
array
hash
]]–



–自定义下标不建议这样使用
local tab1={
11,
22,
33,
“string”
}
tab1[55]=“lua”

for k,v in ipairs(tab1) do
print(k,v)
end
print(“\n”)
for k,v in pairs(tab1) do
print(k,v)
end
print(“\n”)

local tab2={}
for i=-4,4 do
tab2[i]=i*10
end

for k,v in ipairs(tab2) do --遍历的是数组下标从1开始不能是负数下标,如果是负数下标的话跳过负数下标
print(k,v)
end
print(“\n”)
for k,v in pairs(tab2) do
print(k,v)
end
print(“\n”)

–二维数组
local x={
11,
22,
33
}
local y={
44,
55,
66
}
local tab3={
{
11,
22,
33
},
{
44,
55,
66
}
}

for i=1,2 do
for j=1,3 do
print(i,j,tab3[i][j])
end
print(“\n”)
end
print(“\n”)

for k,v in ipairs(tab3) do
for k2,v2 in ipairs(v) do
print(k,k2,v2)
end
print(“\n”)
end
print(“\n”)

for k,v in pairs(tab3) do
for k2,v2 in pairs(v) do
print(k,k2,v2)
end
print(“\n”)
end
print(“\n”)

–自己创建一个二维数组
local tab4={}
for i=1,3 do
tab4[i]={} --因为是二维数组,所以tab4[i]={}一定要
for j=1,2 do
tab4[i][j]=i*j*10
end
end

for k,v in ipairs(tab4) do
for k2,v2 in ipairs(v) do
print(k,k2,v2)
end
print(“\n”)
end


输出结果:



1 11
2 22
3 33
4 string

1 11
2 22
3 33
4 string
55 lua

1 10
2 20
3 30
4 40

1 10
2 20
3 30
4 40
-2 -20
-1 -10
-4 -40
-3 -30
0 0

1 1 11
1 2 22
1 3 33

2 1 44
2 2 55
2 3 66

1 1 11
1 2 22
1 3 33

2 1 44
2 2 55
2 3 66

1 1 11
1 2 22
1 3 33

2 1 44
2 2 55
2 3 66

1 1 10
1 2 20

2 1 20
2 2 40

3 1 30
3 2 60

PS D:\lua代码>


## 15、table操作函数



–[[
—@param list table
—@param sep? string
—@param i? integer
—@param j? integer
—@return string
—@nodiscard
function table.concat(list, sep, i, j) end
—提供一个列表,其所有元素都是字符串或数字,返回字符串 list[i]..sep..list[i+1] ··· sep..list[j]

—@param list table
—@param pos? integer
—@return any
function table.remove(list, pos) end
—移除 listpos 位置上的元素,并返回这个被移除的值。默认不写pos是最后一个位置


—查看文档

—@overload fun(list: table, value: any)
—@param list table
—@param pos integer
—@param value any
function table.insert(list, pos, value) end
—在 list 的位置 pos 处插入元素 value


—查看文档

—@generic T
—@param list T[]
—@param comp? fun(a: T, b: T):boolean
—function table.sort(list, comp)
—在表内从 list[1]list[#list] *原地* 对其间元素按指定次序排序。

—将元素从表 a1 移到表 a2
lua ---a2[t],··· = ---a1[f],···,a1[e] ---return a2 ---



—@param a1 table
—@param f integer
—@param e integer
—@param t integer
—@param a2? table
—@return table a2
function table.move(a1, f, e, t, a2) end
]]–

–table.concat(table, sep, i, j),将表中的元素拼接成一个字符串,sep是连接符号,i是起始位置,j是终止位置
–table.remove(list, pos)移除 listpos 位置上的元素,并返回这个被移除的值。默认不写pos是最后一个位置
–table.insert(list, pos, value) 在 list 的位置 pos 处插入元素 value。默认不写pos是在最后一个位置插入
–table.sort(list, comp) 数组排序,默认从小到大,可自定义排序规则
–table.move(a1, f, e, t, a2) 把数组a1中的元素往a2中拷贝



local tab1={
“abc”,
“DEF”,
“123”,
11,
[“key”]=value,
[“id”]=123
}
print(table.concat(tab1))
print(table.concat(tab1,“–”))
print(table.concat(tab1,“–”,2,3))
print(table.concat(tab1,“–”,1,2))
print(“\n”)

print(table.remove(tab1))
print(table.concat(tab1))
print(table.remove(tab1,1))
print(table.concat(tab1))
print(“\n”)

print(table.insert(tab1,“china”))
print(table.concat(tab1))
print(“\n”)

table.sort(tab1)
print(table.concat(tab1))
print(“\n”)

function cmp(a,b)
return a>b
end
table.sort(tab1,cmp)
print(table.concat(tab1))
print(“\n”)

local tab2={
“a”,
“b”
}

table.move(tab1,1,2,3,tab2) --3指定是第二个表tab2中的位置,这里就是第三个位置,1和2代表tab1中的第一个元素开始和结束就是chinaDEF
print(table.concat(tab1))
print(table.concat(tab2))
print(“\n”)

–下面的两种写法表示一样的效果,没区别
local info1={
id=123,
name=“lua”,
grade=60,
sex=“male”
}
local info2={
[“id”]=123,
[“name”]=“lua”,
[“grade”]=60,
[“sex”]=“male”
}


输出结果:



abcDEF12311
abc–DEF–123–11
DEF–123
abc–DEF

11
abcDEF123
abc
DEF123

DEF123china

123DEFchina

chinaDEF123

chinaDEF123
abchinaDEF

PS D:\lua代码>


## 16、string常用api



–[[

—接收一个字符串,将其中的小写字符都转为大写后返回其副本。

—查看文档

—@param s string
—@return string
—@nodiscard
function string.upper(s) end

return string

---
---将其中的大写字符都转为小写后返回其副本。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.lower"])
---
---@param s string
---@return string
---@nodiscard
function string.lower(s) end

return string

---
---返回其长度。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.len"])
---
---@param s string
---@return integer
---@nodiscard
function string.len(s) end

return number

---
---返回字符串 s 的翻转串。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.reverse"])
---
---@param s string
---@return string
---@nodiscard
function string.reverse(s) end

return string

---
---返回字符串的子串, 该子串从 `i` 开始到 `j` 为止。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.sub"])
---
---@param s  string
---@param i  integer
---@param j? integer
---@return string
---@nodiscard
function string.sub(s, i, j) end

return string

---
---查找第一个字符串中匹配到的 `pattern`(参见 [§6.4.1](command:extension.lua.doc?["en-us/54/manual.html/6.4.1"]))。
---
---
---@param s       string
---@param pattern string
---@param init?   integer
---@param plain?  boolean
---@return integer start
---@return integer end
---@return any ... captured
---@nodiscard
function string.find(s, pattern, init, plain) end

return number

---
---将字符串 s 中,所有的(或是在 n 给出时的前 n 个) pattern (参见 [§6.4.1](command:extension.lua.doc?["en-us/54/manual.html/6.4.1"]))都替换成 repl ,并返回其副本。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.gsub"])
---
---@param s       string
---@param pattern string
---@param repl    string|number|table|function
---@param n?      integer
---@return string
---@return integer count
---@nodiscard
function string.gsub(s, pattern, repl, n) end

return string

---
---接收零或更多的整数。 返回和参数数量相同长度的字符串。 其中每个字符的内部编码值等于对应的参数值。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.char"])
---
---@param byte integer
---@param ... integer
---@return string
---@nodiscard
function string.char(byte, ...) end

return string

---
---返回字符 `s[i]`, `s[i+1]`, ... ,`s[j]` 的内部数字编码。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.byte"])
---
---@param s  string
---@param i? integer
---@param j? integer
---@return integer ...
---@nodiscard
function string.byte(s, i, j) end

return number

]]–



local str1=“abCD1234”
local str2=string.upper(str1) --接收一个字符串,将其中的小写字符都转为大写后返回其副本。
print(str2)
local str3=string.lower(str1) --接收一个字符串,将其中的大写字符都转为小写后返回其副本。
print(str3)
print(“\n”)

print(string.len(str1)) --接收一个字符串,返回其长度。
print(string.len(“你好1bc a”)) --其中一个汉字是3个字符,总共11个字符
print(“\n”)

print(string.reverse(str1)) --接收一个字符串,返回字符串 s 的翻转串。
print(“\n”)

local a=0000
print(“china”…" is"…" best"…" country!“…” str1"…1 …1 …a…2) – … 连接符,number 如果在连接符左边,后面要空格
print(“\n”)

print(string.sub(str1,2)) --返回字符串的子串, 该子串从 i 开始到 j 为止。默认有两个参数
print(string.sub(str1,1,2))
print(string.sub(str1,-4,-2)) --负数是从右往左数
print(“\n”)

print(string.find(str1,1)) – 在字符串s中 查找pattern(可以是表达式),如果找到,则返回pattern 第一次出现的开始位置和结束位置,如果没找到,返回nil
print(string.find(str1,“abC”))
print(string.find(str1,“ab”,3)) --从指定位置开始寻找
print(string.find(str1,“ab”,3,5))
print(string.find(str1,“ab”,-8)) --负数是从右往左数
print(“\n”)

print(string.find(str1,“%d”,1)); --最后一个参数,默认就是false,开启正则匹配模式,这里寻找的是%d number型
print(string.find(str1,“(%d%d%d%d)”))
print(string.find(str1,“%d”,6,true));–最后一个参数,true 是直接当子串处理
print(“\n”)

print(string.gsub(str1,1,2)) --全部替换
print(string.gsub(str1,“ab”,“AB”,2)) --最多替换两次
print(“\n”)

print(string.char(65)) --asscil码转字符,数字只能是0~255
print(string.byte(“a”)) --字符转asscil码
print(string.byte(“abc”,1,2)); --1和2代表转几个
print(string.byte(“abc”,1,3));


输出结果:



ABCD1234
abcd1234

8
11

4321DCba

china is best country! str11102

bCD1234
ab
123

5 5
1 3
nil
nil
1 2

5 5
5 8 1234
nil

abCD2234 1
ABCD1234 1

A
97
97 98
97 98 99
PS D:\lua代码>


## 17、function常见表示形式



–[[

function进阶,常见的表现形式
    --函数普通函数

    --函数当右值,赋值给一个变量

    --匿名函数当右值

    --函数当参数

    --函数当返回值

    --匿名函数当返回值

    --函数多返回值

]]–



–普通函数
function show(a,b)
print(a,b)
end
–函数直接调用
show(“abc”,123)

–函数当右值,赋值给一个变量
func1=show
func1(“abc”,123)

–匿名函数当右值
func2=function(a,b)
print(“abc”,123)
end
func2()

–函数当参数
function func3(func,a,b)
func(a,b)
end
func3(show,“abc”,123)
func3(
function(a, b)
print(a, b)
end,
“abc”, “123”
)
print(“\n”)

–函数当返回值
function func4()
return func1
end
fun1=func4()
fun1(“abc”,123)
func4()(“abc”,123)

–匿名函数当返回值
function func5()
return function(a,b)
print(a,b)
end
end
fun2=func5()
fun2(“abc”,123)
func5()(“abc”,123)
print(“\n”)

–函数多返回值
function func6()
function func6_son1(a,b)
print(“son1”,a,b)
end
function func6_son2(a,b)
print(“son2”,a,b)
end
return func6_son1,
func6_son2,
func1,
function(a,b)
print(“son_last”,a,b)
end
end

fun3,fun4,fun5,fun6=func6()
fun4(“abc”,123)
fun5(“abc”,123)
fun6(“abc”,123)
fun3(“abc”,123)


输出结果:



abc 123
abc 123
abc 123
abc 123
abc 123

abc 123
abc 123
abc 123
abc 123

son2 abc 123
abc 123
son_last abc 123
son1 abc 123
PS D:\lua代码>


## 18、table中的function



–[[

function进阶,table中的function

]]–

function show(a)
print(a)
end

local tab1={
t1_show=show,
add=function(a,b)
return a+b
end
}
tab1.sub=function(a,b)
return a-b
end
tab1[“mul”]=function(a,b)
return a*b
end
tab1[“div”]=function(a,b)
return a/b
end

tab1.t1_show(“abc”)
tab1.t1_show(tab1.add(11,22))
tab1"t1_show"
tab1.t1_show(tab1.sub(11,22))
tab1.t1_show(tab1.mul(11,22))
tab1.t1_show(tab1.div(11,22))
print(“\n”)

calc={
add=function(a,b)
return a+b
end,
sub=function(a,b)
return a-b
end,
mul=function(a,b)
return a*b
end,
sub=function(a,b)
return a/b
end,
show=function(a)
print(a)
end
}

calc.show(calc.add(11,22))
calc.show(calc.sub(11,22))
calc.show(calc.mul(11,22))
calc.show(calc.sub(11,22))

tab2={
a=0,
b=0,
result=0,
add=function()
tab2.result=tab2.a+tab2.b
end,
sub=function()
tab2.result=tab2.a-tab2.b
end,
mul=function()
tab2.result=tab2.a*tab2.b
end,
div=function()
tab2.result=tab2.a/tab2.b
end,
show=function()
print (tab2.result)
end
}

tab2.a=11
tab2.b=22
tab2.add()
tab2.show()


输出结果:



abc
33
123
-11
242
0.5

33
0.5
242
0.5

33
0.5
242
0.5
33


## 19、用select处理可变参数



–[[

关于用select处理可变参数

select(n,...),表示获取可变参数的一部分数据从n开始
select("#",...),表示获取可变参数的个数

 ---
---接收任意数量的参数,并将它们的值打印到 `stdout`。 它用 `tostring` 函数将每个参数都转换为字符串。 
--`print` 不用于做格式化输出。仅作为看一下某个值的快捷方式。 多用于调试。 
--完整的对输出的控制,请使用 [string.format](command:extension.lua.doc?["en-us/54/manual.html/pdf-string.format"])
-- 以及 [io.write](command:extension.lua.doc?["en-us/54/manual.html/pdf-io.write"])。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-print"])
---

---
---如果 `index` 是个数字, 那么返回参数中第 `index` 个之后的部分; 负的数字会从后向前索引(`-1` 指最后一个参数)。 
--否则,`index` 必须是字符串 `"#"`, 此时 `select` 返回参数的个数。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-select"])
---
---@param index integer|'"#"'
---@return any
---@nodiscard
function select(index, ...) end

]]–



local function func1(…)
print(select(1,…))
print(select(2,…))
print(select(3,…))
print(select(4,…))
print(select(5,…))
print(select(“#”,…))

local sum=0
local count=select("#",...)
for i=1,count do
    sum=sum+(select(i,...))
end
return sum

end

print(func1(11,22,33,44,55))
print(“\n”)

local function func2()
return 11,22,33
end

local function func3()
return 111,222,333
end

print(func2())
print(func3())
print(“\n”)
print((func2()))
print((func3()))
print(“\n”)
print(func2(),“=“,func3())
print((func2()),”
=”,func3())


输出结果:



11 22 33 44 55
22 33 44 55
33 44 55
44 55
55
5
165

11 22 33
111 222 333

11
111

11 === 111 222 333
11 === 111 222 333
PS D:\lua代码>


## 20、用pack处理可变参数



–[[

---用pack 处理函数可变参数
---table.pack(...) 将可变参打包成一个table,且会在最后多出一个n键,其对应的值是可变参的参数个数
---table.unpack(list, i, j) 解包,将table 解成可变参

---
---返回用所有参数以键 `1`,`2`, 等填充的新表, 并将 `"n"` 这个域设为参数的总数。
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-table.pack"])
---
---@return table
---@nodiscard
function table.pack(...) end

---
---返回列表中的元素。 这个函数等价于
---```lua
---    return list[i], list[i+1], ···, list[j]
---```
---i 默认为 1 ,j 默认为 #list。
---
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-table.unpack"])
---
---@generic T
---@param list T[]
---@param i?   integer
---@param j?   integer
---@return T   ...
---@nodiscard
function table.unpack(list, i, j) end

]]–



local function func1(…)
print(table.pack(…).n)

local sum=0
local tab1=table.pack(...)
for k,v in pairs(tab1) do
    if k~="n" then
        sum=sum+v
    end
end

local count=tab1.n
print(count)
for i=1,count do
    if tab1[i]~=nil then
        sum=sum+tab1[i]
    end
end

return sum

end

print(func1(11,22,nil,33,44,55,nil))
print(“\n”)

local function func2()
–return 11,22,33,44,55,66
return table.pack(11,22,33,44,55,66)
end

print(11,22,33,44,55,66)
print(func2())
print(table.unpack(func2()))
print(table.unpack(func2(),1,2))
print(“\n”)

local tab2=func2()
print(table.unpack(tab2))
print(“\n”)

—可变参转成table
local function func3(…)
local sum=0
local tab1={…}
local count=#tab1
print(count)
for k,v in pairs(tab1) do
if k~=“nil” then
sum=sum+v
end
print(k,v)
end
return sum
end

print(func3(11,22,nil,33,44,nil,55,66,77))


输出结果:



7
7
330

11 22 33 44 55 66
table: 000001926BF91DE0
11 22 33 44 55 66
11 22

11 22 33 44 55 66

9
1 11
2 22
4 33
5 44
7 55
8 66
9 77
308
PS D:\lua代码>


## 21、lua中闭包 (closure)的实现



–[[

闭包

百度百科 https://baike.baidu.com/item/闭包/10908873

闭包就是能够读取其他函数内部变量的函数。
例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。
在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

lua
当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,
这种特征在lua中我们称作词法定界。
虽然这看起来很清楚,事实并非如此。
词法定界加上第一类函数在编程语言里是一个功能强大的概念,很少语言提供这种支持。

个人理解
闭包就是指一种编码方式,一种思想,而不是指某种具体的技术或函数或库

内部函数读取外部函数的变量

lambda 表达式,经典的闭包表现方式之一

]]–


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8m1N0Ihi-1665330518835)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221004001207777.png)]



local function func1(a,b)
local x=0
local y=0
return function()
x=x+1 --类似static属性,内部匿名函数访问外部函数func1的变量x
print(a,b,x,y)
end
end

func1(“abc”,123)()
print(“\n”)

local tmp1=func1(“abc”,123)
tmp1()
tmp1()
tmp1()
tmp1()
print(“\n”)

local tmp2=func1(“abc”,123)
tmp2()


输出结果:



abc 123 1 0

abc 123 1 0
abc 123 2 0
abc 123 3 0
abc 123 4 0

abc 123 1 0
PS D:\lua代码>


## 22、用闭包 (closure)实现ipairs迭代器


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NaoNqpue-1665330518835)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221004002633436.png)]




---


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f2KRhXAO-1665330518836)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221004003844556.png)]



–[[

迭代器

百科百科 https://baike.baidu.com/item/迭代器

迭代器(iterator)有时又称光标(cursor)是程序设计的软件设计模式,
可在容器对象(container,例如链表或数组)上遍访的接口,
设计人员无需关心容器对象的内存分配的实现细节。


---
---如果 `t` 有元方法 `__pairs`, 以 `t` 为参数调用它,并返回其返回的前三个值。
---
---否则,返回三个值:`next` 函数, 表 `t`,以及 `nil`。 因此以下代码
---```lua
---    for k,v in pairs(t) do body end
---```
---能迭代表 `t` 中的所有键值对。
---
---参见函数 [next](command:extension.lua.doc?["en-us/54/manual.html/pdf-next"]) 中关于迭代过程中修改表的风险。
---
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-pairs"])
---
---@generic T: table, K, V
---@param t T
---@return fun(table: table<K, V>, index?: K):K, V
---@return T
function pairs(t) end

---
---返回三个值(迭代函数、表 `t` 以及 `0` ), 如此,以下代码
---```lua
---    for i,v in ipairs(t) do body end
---```
---将迭代键值对 `(1,t[1]) ,(2,t[2]), ...` ,直到第一个空值。
---
---
---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-ipairs"])
---
---@generic T: table, V
---@param t T
---@return fun(table: V[], i?: integer):integer, V
---@return T
---@return integer i
function ipairs(t) end

]]–



local tab1={
11,
22,
33,
nil,
[“string”]=“lua”,
44,
nil,
55
}

for k,v in pairs(tab1) do
print(k,v)
end
print(“\n”)

for k,v in ipairs(tab1) do
print(k,v)
end
print(“\n”)

local function MyIpairs(tab1)
local count=#tab1
local index=0

return function()
    if index <= count then
        index=index+1
        if tab1[index]~=nil then
            return index,tab1[index]
        end
    end
end

end

local function MyPairs(tab1)
local count=#tab1
local index=0

return function()
    if index<=count then
        index=index+1
        -- if tab1[index]~=nil then
        -- return index,tab1[index]
        -- else
        -- index=index+1
        -- return index,tab1[index]
        -- end
        if tab1[index] == nil then
            index=index+1
        end
        return index,tab1[index]
    end
end

end

for k,v in MyIpairs(tab1) do
print(k,v)
end
print(“\n”)

for k,v in MyPairs(tab1) do
print(k,v)
end


输出结果:



1 11
2 22
3 33
5 44
7 55
string lua

1 11
2 22
3 33

1 11
2 22
3 33

1 11
2 22
3 33
5 44
7 55
9 nil
PS D:\lua代码>


## 23、元表和元方法(一)


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2E3VOrse-1665330518837)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221004213130240.png)]



–[[

元表 metatable

元表并不是一个普通的表,而是一套自定义的计算规则,用这些规则,可以实现表与表之间的运算
而这些规则,都以函数的方式,写在元表中,所以又称为元方法(就是写在元表里面的方法)

起到一个类似于其它语言中的运算符重载的作用

setmetatable(table, metatable) – 将 metatable 设为 table 的元表,其返回值为table


—给指定表设置元表。 (你不能在 Lua 中改变其它类型值的元表,那些只能在 C 里做。
—如果 metatablenil, 将指定表的元表移除。 如果原来那张元表有 "\_\_metatable" 域,抛出一个错误。


—查看文档

—@param table table
—@param metatable? table
—@return table
function setmetatable(table, metatable) end
]]–



local tab1={
11,
22,
33,
44
}
local tab2={
111,
222,
333,
nil,
444,
nil
}
local tab11={
11,
22,
33,
44
}
local tab22={
111,
222,
333,
nil,
444,
nil
}
local metaTab3={}
setmetatable(tab1,metaTab3)
setmetatable(tab2,metaTab3)
local tab5={
"china ",
"best ",
"country ",
1
}
local tab6={
"is ",
"of ",
2
}
local metaTab4={}
setmetatable(tab5,metaTab4)
setmetatable(tab6,metaTab4)

metaTab3[“__add”]=function (t1,t2)
local res={}
local len1=#t1
local len2=#t2
if len1 >len2 then
len2=len1
end
for i=1,len2 do
– res[i]=t1[i]+t2[i]
local a=t1[i] or 0
local b=t2[i] or 0
res[i]=a+b
end
return res
end

metaTab4.__add=function(t1,t2)
local res={}
local len1=#t1
local len2=#t2
if len1> len2 then
len2=len1
end
for i=1,len2 do
local a=t1[i] or “”
local b=t2[i] or “”
res[i]=a…b
end
return res
end

local metaTab5={}
setmetatable(tab11,metaTab5)
setmetatable(tab22,metaTab5)
metaTab5[“__eq”]=function(t1,t2)
if #t1~=t2 then
return false
end
for i=1,#t1 do
if t1[i] ~= t2[i] then
return false
end
end
return true
end

local tab3=tab1+tab2
print(tab3)
for k,v in ipairs(tab3) do
print(k,v)
end
print(“\n”)

local tab4=tab5+tab6
print(tab4)
print(tab5)
print(tab6)
for k,v in ipairs(tab4) do
print(k,v)
end
print(“\n”)

print(tab11==tab22)


输出结果:



table: 00000290A537E1E0
1 122
2 244
3 366
4 44
5 444

table: 00000290A537D9A0
table: 00000290A537D820
table: 00000290A537D720
1 china is
2 best of
3 country 2
4 1

false
PS D:\lua代码>


## 24、元表和元方法(二)



–[[

元表 metatable

__index
当在一个表中,去取某个key
如果该表中有对应的key,就直接返回
如果没有
看有没有元表
没有元表,返回nil
有元表
看元表中有没有__index
没有,返回nil

如果__index 是个表,
并且有key, 返回值
没有key, 返回nil

如果 __index 是个function
则直接调用该function ,且表和key 都会作为该function 的参数

__newindex
如果是表,则在本表里面设一个没有的key的时候,会写到__newindex 对应的表中,而不会写自己的表
如果本表中有key,则更新本表,不会管元表

如果是function,则直接调用,且本表,key,value 都可作参数
]]–



local tab1={
[“id”]=123,
[“country”]=“china”,
[“province”]=“shanghai”,
–[“phone”]=“new_phone”
}

local meta={
–__index={} --—__index是个空表
–__index={phone=“index_phone”} —__index是一个表
__index=function(t,k)
–print(t,k)
t[k]=“new_phone”
return “index_phone”
end
}

– mm.__index={
– id=123,
– [“name”]=“tom”
– }
– setmetatable(tab1,mm.__index)

print(tab1.phone) --没有key,直接返回nil
setmetatable(tab1,meta) --设置meta为tab1的元表,但没有index表返回nil,有则查找index表
print(tab1.phone) --元表中有key,返回value
tab1.phone=nil --把自己表中的key去掉
print(tab1.phone) --自己tab1中有key,直接返回value

local tab2={}
meta.__index=tab2
print(tab1.phone) --new_phone
print(“\n”)

local tab3={
[“id”]=123,
[“country”]=“china”,
[“province”]=“shanghai”,
–[“phone”]=“new_phone”
}
local tab4={}

local meta2={
–__newindex=tab4
__newindex=function(t,k,v)
–print(t,k,v)
print(tostring(t)…" written to “…k…”:"…v)
–t[k]=v --C stack overflow 死递归,爆栈了
rawset(t,k,v) --调用原生方法,不调用重载的方法
end
}
print(tab3.phone)
setmetatable(tab3,meta2)
tab3[“phone”]=“new_phone” --当有__newindex 的时候,就写到对应的__newindex 的表中去了
print(tab3.phone)
print(tab4.phone)

meta2.__index=tab4
print(tab3.phone)


输出结果:



nil
index_phone
index_phone
new_phone

nil
table: 000002446D03BD00 written to phone:new_phone
new_phone
nil
new_phone
PS D:\lua代码>


## 25、元表和元方法(三)



–[[

元表 metatable

__tostring 用函数接管本表的返回值 返回一个string
__call 把表当类处理,此处类似于类中的构造函数,可传值,本表是第一个参数

rawget(table, index) 取本表中的index 索引对应的值,不受元表干扰,没有就返回nil;
rawset(table, index, value) 给本表添加元素,不受元表干扰


—在不触发任何元方法的情况下 获取 table[index] 的值。 table 必须是一张表; index 可以是任何值。

—查看文档

—@param table table
—@param index any
—@return any
—@nodiscard
function rawget(table, index) end


—在不触发任何元方法的情况下 将 table[index] 设为 value。 table 必须是一张表, index 可以是 nilNaN 之外的任何值。 value 可以是任何 Lua 值。
—这个函数返回 table


—查看文档

—@param table table
—@param index any
—@param value any
—@return table
function rawset(table, index, value) end
]]–



local tab1={
[“id”]=123,
[“name”]=“tom”
}

local meta={}
setmetatable(tab1,meta)

print(tab1)
print(tab1.phone)
print(“\n”)

meta.__tostring=function(t)
local str=“”
for k,v in pairs(t) do
str=str…k…" : "…v
end
t[“phone”]=123456
return str
end

print(tab1)
print(tab1.phone) --在上一句执行完之后,才有phone 字段
print(“\n”)

meta.__call=function(t,…)
print(t)
print(…)
local t2={}
for k,v in pairs(t2) do
print(k,v)
end
end

tab1(123)
print(“\n”)
tab1()
print(“\n”)

local tab2={
[“id”]=123,
[“name”]=“tom”
}
local tab3={}

print(tab2.id)
print(tab2.phone)
print(“\n”)

local MT={
–__index={phone=123456}
__index=function(t,k)
print(t,k)
end,

__newindex=tab3

}
setmetatable(tab2,MT)
print(tab2.id)
print(tab2.phone)
print(“\n”)
print(rawget(tab2,“id”))
print(rawget(tab2,“phone”))
print(“\n”)
print(“\n”)

print(tab2.country)
–tab2.country=“china”
rawset(tab2,“country”,“china”)
print(tab2.country,tab3.country)


输出结果:



table: 000001DCDA5A0770
nil

name : tomid : 123
123456

name : tomphone : 123456id : 123
123

name : tomphone : 123456id : 123

123
nil

123
table: 000001DCDA5A15F0 phone
nil

123
nil

table: 000001DCDA5A15F0 country
nil
china nil
PS D:\lua代码>


## 26、面向对象 self



–[[

类 class
对象 new class(实例化)
继承、构造、析构

table={}
metatable={}
self

]]–


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TeV4I1WZ-1665330518838)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005183655058.png)]



tab1={
[“id”]=123,
[“name”]=“tom”,
[“getId”]=function()
return tab1.id
end
}
print(tab1.id,tab1.name,tab1.getId())
print(“\n”)

local tab2=tab1
print(tab1,tab2)
tab1=nil
print(tab2.id,tab2.name)
print(tab2.getId())


输出结果:



123 tom 123

table: 0000022D822910F0 table: 0000022D822910F0
123 tom
C:\Users\hp.vscode\extensions\actboy168.lua-debug-1.60.0-win32-x64\runtime\win32-x64\lua54\lua.exe: …于面向对象/lua关于面向对象_self/lua关于面
向对象_self.lua:17: attempt to index a nil value (global ‘tab1’)
stack traceback:
…于面向对象/lua关于面向对象_self/lua关于面向对象_self.lua:17: in field ‘getId’
…于面向对象/lua关于面向对象_self/lua关于面向对象_self.lua:27: in main chunk
[C]: in ?
PS D:\lua代码>


此时print(tab2.getId())发生错误,错误结果如上图所知,tab1=nil之后,tab2就不能找到tab1.id了。


解决办法1:把对象当做参数传过去



tab1={
[“id”]=123,
[“name”]=“tom”,
[“getId”]=function()
return tab1.id
end,
[“getName”]=function(obj)
return obj.name
end
}
–print(tab2.getId())
print(tab2.getName(tab2))


输出结果:



tom


解决办法2:引入像this指针一样的self引用



tab1={
[“id”]=123,
[“name”]=“tom”,
[“getId”]=function()
return tab1.id
end,
[“getName”]=function(obj)
return obj.name
end
}

function tab1:getId2()
return self.id
end
function tab1:getName2()
return self.name
end

print(tab1.id,tab1.name,tab1.getId())
print(“\n”)

local tab2=tab1
print(tab1,tab2)
tab1=nil
print(tab2.id,tab2.name)
–print(tab2.getId())
print(tab2.getName(tab2))
print(“\n”)

print(tab2:getId2(),tab2:getName2())


输出结果:



123 tom 123

table: 0000026284C41610 table: 0000026284C41610
123 tom
tom

123 tom
PS D:\lua代码>


## 27、面向对象自索引


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bPsUuOup-1665330518838)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005191539388.png)]



–[[

自索引 自己索引自己

]]–

local tab1={
[“id”]=123,
[“name”]=“tom”
}

local indexTable={
[“phone”]=123456
}

local meta={
–__index=indexTable
__index=meta, --此处meta不存在,所以索引__index=nil
[“phone”]=123456
}

–meta.__index=meta --自己索引自己,这就是自索引
setmetatable(tab1,meta)

print(tab1.phone)
print(“\n”)

print(tab1,indexTable,meta)


输出结果:



nil

table: 000001EA7DEE1720 table: 000001EA7DEE1AA0 table: 000001EA7DEE1760
PS D:\lua代码>


## 28、面向对象自索引实现继承



–[[

自索引: 自己索引自己

用自索引实现继承

典型的面向对象写法:子类继承父类,子类调用父类方法
]]



local father={
[“id”]=123,
[“name”]=“father”
}

function father:fasy()
print(“father say”,self.id,self.name)
end

father.__index=father --父类加自索引

local son={
[“id”]=456,
[“name”]=“son”
}
function son:sonsy()
print(“son say”)
end
setmetatable(son,father) --设置子类的元表为父类

father:fasy()
son:sonsy()
print(“\n”)

son:fasy()


输出结果:



father say 123 father
son say

father say 456 son
PS D:\lua代码>


## 29、面向对象类的实例化



–[[

类 class
对象   new class()
继承,构造,析构

table {}
metatable {}

class x{
    ....
}

]]–


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6AWXUBTq-1665330518840)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005195039237.png)]


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZxPgmqge-1665330518840)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005201428470.png)]



local userinfo={
[“id”]=123,
[“name”]=“tom”,
[“age”]=23
}
userinfo.__index=userinfo --自索引

local u1=userinfo
local u2=u1
print(userinfo.id,u1.id,u2.id)
u2.id=456
print(userinfo,u1,u2)
print(userinfo.id,u1.id,u2.id)
print(“\n”)
function userinfo:new(obj)
– local obj=obj or {}
obj=obj or {}
setmetatable(obj,self) --元表继承
return obj
end
function userinfo:setAeg(val)
self.age=self.age+val
return self.age
end

– local u3=userinfo:new({[“id”]=789,[“name”]=“jerry”})
local u3=userinfo:new({[“id”]=789})
userinfo.name=“jerry”
print(u3)
print(u2.id,u3.id)
print(“\n”)
print(u2.name,u3.name)
u3.name=“tom” --__newindex
print(u2.name,u3.name)
userinfo.name=“lucy”
print(u2.name,u3.name)
print(“\n”)

print(u2.age,u3.age)
u3:setAeg(100)
print(u2.age,u3.age)


输出结果:



123 123 123
table: 0000016CCBEB43F0 table: 0000016CCBEB43F0 table: 0000016CCBEB43F0
456 456 456

table: 0000016CCBEB4370
456 789

jerry jerry
jerry tom
lucy tom

23 23
23 123
PS D:\lua代码>


## 30、面向对象多重继承


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n9LV61Kl-1665330518841)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221005203241755.png)]



–[[

–多重继承
]]

local grandFather={
[“id”]=123,
[“name”]=“grandFather”
}

grandFather.__index=grandFather

local father={
–[“id”]=456,
[“name”]=“father”
}
father.__index=father
setmetatable(father,grandFather)

local son={
–[“id”]=789,
[“name”]=“son”
}
setmetatable(son,father)

print(grandFather.id);–找自己有没有 id 这个索引,有,直接发返回123

print(father.id);–先找自己,没有 id 这个索引,所以看有没有元表,元表是 grandfather,然后去找 grandfather的 __index,找到,所以返回123

print(son.id);–先找自己,没有 id 这个索引,所以看有没有元表,元表是 father,然后去找 father的 __index,
– father.__index 里面也没有 id 这个索引,但是 father.__index 有元表,是 grandfather
– 所以去找 grandfather.__index 里面有没有 id 这个索引,有,所以返回123

print(grandFather.name,father.name,son.name);
print(“\n”)

local userInfo={
[“id”]=456,
[“name”]=“tom”,
[“age”]=23
}

function userInfo:new(obj)
obj=obj or {}

self.__index=self        --父类自己索引自己

setmetatable(obj,self)  ---谁调用new 方法,此处的 元表self 就是谁
return obj

end

local u1=userInfo:new({[“id”]=456})
print(userInfo.id,u1.id)
print(userInfo.name,u1.name)
print(“\n”)

local u2=u1:new()
print(userInfo.id,u1.id,u2.id)
print(userInfo.name,u1.name,u2.name)
print(“\n”)

local u3=u2:new({[“age”]=22})

print(userInfo.id,u1.id,u2.id,u3.id)
print(userInfo.name,u1.name,u2.name,u3.name)
print(userInfo.age,u1.age,u2.age,u3.age)


输出结果:



123
123
123
grandFather father son

456 456
tom tom

456 456 456
tom tom tom

456 456 456 456
tom tom tom tom
23 23 23 22
PS D:\lua代码>


## 31、面向对象重写



–[[

重写

]]

local userInfo={
[“id”]=123,
[“name”]=“tom”
}

function userInfo:new(obj)
obj=obj or {}
setmetatable(obj,self) —谁调用new 方法,此处的 元表self 就是谁
self.__index=self —父类的索引
return obj
end

function userInfo:say()
print(“useinfo say”)
end

local u1=userInfo:new()
local u2=u1:new({[“id”]=456})
print(userInfo.id,u1.id,u2.id)
print(userInfo.name,u1.name,u2.name)
print(“\n”)

u1[“phone”]=12312
print(userInfo.phone,u1.phone,u2.phone)
u1.phone=nil
print(userInfo.phone,u1.phone,u2.phone)
print(“\n”)

userInfo:say()
u1:say()
u2:say()
print(“\n”)

function u1:say()
print(“u1 say”)
end
u1:say()
print(“\n”)

function u2:hello()
print(“u2 hello”)
end
–userInfo:hello()
–u1:hello()
u2:hello()


输出结果:



123 123 456
tom tom tom

nil 12312 12312
nil nil nil

useinfo say
useinfo say
useinfo say

u1 say

u2 hello
PS D:\lua代码>


## 32、面向对象成员私有化



–[[

成员私有化
]]

function userInfo()
local member={
[“id”]=123,
[“name”]=“tom”,
[“province”]=“shanghai”
}
local function getId()
return member.id
end
local function setId(val)
member.id=val
end

--只暴露方法给外面,表中成员变量私有化
return {
    getId=getId,   --左边key,右边value
    setId=setId,

    getName=function()
        return member.name
    end
}

end

print(userInfo().getName())
print(userInfo().getId())
print(“\n”)

local users=userInfo()
print(users.getId())
print(users.getName())
print(users.setId(456))
print(users.getId())


输出结果:



tom
123

123
tom

456
PS D:\lua代码>


## 33、协程(coroutine)



–[[

协程

协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。
一个程序可以包含多个协程,可以对比与一个进程包含多个线程,因而下面我们来比较协程和线程。
我们知道多个线程相对独立,有自己的上下文,切换受系统控制;
而协程也相对独立,有自己的上下文,但是其切换由自己控制,由当前协程切换到其他协程由当前协程来控制。

【可以把协程看成是一个可以自己自行决定调度切换的线程】

编程语言Lua从5.0版开始支持协程的概念,极大的扩展了Lua的能力。Lua的协程通过扩展库coroutine来实现

百度百科 https://baike.baidu.com/item/协程/8652240

API https://www.lua.org/manual/5.4/manual.html#6.2

这里co是协程句柄,由coroutine.create()创建。

coroutine.close (co) -------------------- 关闭协程,返回bool
coroutine.create (f) -------------------- 创建协程,传入一个function,返回一个协程句柄
coroutine.isyieldable ([co]) ------------ 判断协程是否是 yield 状态
coroutine.resume (co [, val1, ···]) ----- 将挂起态的协程重新激活
coroutine.running () -------------------- 获取正在运行的协程
coroutine.status (co) ------------------- 获取co句柄对应的协程的状态 [suspended(挂起),running(执行中),dead(结束)]
coroutine.wrap (f) ---------------------- 用function 创建一个新的协程
coroutine.yield (···) ------------------- 挂起当前协程

对于线程
线程(英语:thread)是操作系统能够进行运算调度的最小单位。
它被包含在进程之中,是进程中的实际运作单位。
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
在Unix System V及SunOS中也被称为轻量进程(lightweight processes),
但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

线程是独立调度和分派的基本单位。线程可以为操作系统内核调度的内核线程,
如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如 Windows 7的线程,进行混合调度。

同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。
但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己 的线程本地存储(thread-local storage)。
一个进程可以有很多线程,每条线程并行执行不同的任务。

在多核或多CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执 行吞吐率。
在单CPU单核的计算机上,使用多线程技术,也可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计 算的部分分开来执行,
编写专门的workhorse线程执行密集计算,从而提高了程序的执行效率。
https://baike.baidu.com/item/%E7%BA%BF%E7%A8%8B/103101?fromModule=lemma- qiyi_sense-lemma

对于进程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位, 是操作系统结构的基础。
在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;
在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的 实体。
https://baike.baidu.com/item/%E8%BF%9B%E7%A8%8B/382503?fromModule=lemma-qiyi_sense-lemma
]]–


协程主要函数如下:



—@meta

    ---
    ---
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine"])
    ---
    ---@class coroutinelib
    coroutine = {}

    ---
    ---创建一个主体函数为 `f` 的新协程。 f 必须是一个 Lua 的函数。 返回这个新协程,它是一个类型为 `"thread"` 的对象。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.create"])
    ---
    ---@param f async fun()
    ---@return thread
    ---@nodiscard
    function coroutine.create(f) end

    ---
    ---如果协程 `co` 可以让出,则返回真。`co` 默认为正在运行的协程。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.isyieldable"])
    ---
    ---@param co? thread
    ---@return boolean
    ---@nodiscard
    function coroutine.isyieldable(co) end

    ---@version >5.4
    ---
    ---关闭协程 `co`,并关闭它所有等待 \*to-be-closed\* 的变量,并将协程状态设为 `dead` 。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.close"])
    ---
    ---@param co thread
    ---@return boolean noerror
    ---@return any errorobject
    function coroutine.close(co) end

    ---
    ---开始或继续协程 `co` 的运行。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.resume"])
    ---
    ---@param co thread
    ---@param val1? any
    ---@return boolean success
    ---@return any ...
    function coroutine.resume(co, val1, ...) end

    ---
    ---返回当前正在运行的协程加一个布尔量。 如果当前运行的协程是主线程,其为真。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.running"])
    ---
    ---@return thread running
    ---@return boolean ismain
    ---@nodiscard
    function coroutine.running() end

    ---
    ---以字符串形式返回协程 `co` 的状态。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.status"])
    ---
    ---@param co thread
    ---@return
    ---| '"running"' # 正在运行。
    ---| '"suspended"' # 挂起或是还没有开始运行。
    ---| '"normal"' # 是活动的,但并不在运行。
    ---| '"dead"' # 运行完主体函数或因错误停止。
    ---@nodiscard
    function coroutine.status(co) end

    ---
    ---创建一个主体函数为 `f` 的新协程。 f 必须是一个 Lua 的函数。 返回一个函数, 每次调用该函数都会延续该协程。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.wrap"])
    ---
    ---@param f async fun()
    ---@return fun(...):...
    ---@nodiscard
    function coroutine.wrap(f) end

    ---
    ---挂起正在调用的协程的执行。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.yield"])
    ---
    ---@async
    ---@return any ...
    function coroutine.yield(...) end

    return coroutine


–业务,取钱,取100w
local function func1(a,b)

local aa=a\*2
local bb=b\*2
local x,y,z=coroutine.yield(aa,bb,"100w")
print(x,y,z)

print(coroutine.status(handle)) --这里能看出协程是执行中
print("\n")

end

handle=coroutine.create(func1) — 去银行办业务, 然后告诉大堂经理,要取现金(要执行func1),大堂经理会帮你叫号,给你一个小票(handle)
print(handle)

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

oroutine.create"])

—@param f async fun()
—@return thread
—@nodiscard
function coroutine.create(f) end

    ---
    ---如果协程 `co` 可以让出,则返回真。`co` 默认为正在运行的协程。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.isyieldable"])
    ---
    ---@param co? thread
    ---@return boolean
    ---@nodiscard
    function coroutine.isyieldable(co) end

    ---@version >5.4
    ---
    ---关闭协程 `co`,并关闭它所有等待 \*to-be-closed\* 的变量,并将协程状态设为 `dead` 。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.close"])
    ---
    ---@param co thread
    ---@return boolean noerror
    ---@return any errorobject
    function coroutine.close(co) end

    ---
    ---开始或继续协程 `co` 的运行。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.resume"])
    ---
    ---@param co thread
    ---@param val1? any
    ---@return boolean success
    ---@return any ...
    function coroutine.resume(co, val1, ...) end

    ---
    ---返回当前正在运行的协程加一个布尔量。 如果当前运行的协程是主线程,其为真。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.running"])
    ---
    ---@return thread running
    ---@return boolean ismain
    ---@nodiscard
    function coroutine.running() end

    ---
    ---以字符串形式返回协程 `co` 的状态。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.status"])
    ---
    ---@param co thread
    ---@return
    ---| '"running"' # 正在运行。
    ---| '"suspended"' # 挂起或是还没有开始运行。
    ---| '"normal"' # 是活动的,但并不在运行。
    ---| '"dead"' # 运行完主体函数或因错误停止。
    ---@nodiscard
    function coroutine.status(co) end

    ---
    ---创建一个主体函数为 `f` 的新协程。 f 必须是一个 Lua 的函数。 返回一个函数, 每次调用该函数都会延续该协程。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.wrap"])
    ---
    ---@param f async fun()
    ---@return fun(...):...
    ---@nodiscard
    function coroutine.wrap(f) end

    ---
    ---挂起正在调用的协程的执行。
    ---
    ---[查看文档](command:extension.lua.doc?["en-us/54/manual.html/pdf-coroutine.yield"])
    ---
    ---@async
    ---@return any ...
    function coroutine.yield(...) end

    return coroutine


–业务,取钱,取100w
local function func1(a,b)

local aa=a\*2
local bb=b\*2
local x,y,z=coroutine.yield(aa,bb,"100w")
print(x,y,z)

print(coroutine.status(handle)) --这里能看出协程是执行中
print("\n")

end

handle=coroutine.create(func1) — 去银行办业务, 然后告诉大堂经理,要取现金(要执行func1),大堂经理会帮你叫号,给你一个小票(handle)
print(handle)

[外链图片转存中…(img-77dbWUTt-1715280336788)]
[外链图片转存中…(img-lPb2qLst-1715280336788)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 25
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值