学习视频连接
首先 感谢UP主
vs code 安装插件
01_Hello World.lua
print("Hello world")
-- 单行注释
--[[
多行注释
]]
--[[
第二种多行注释
]]--
--[[
第三种多行注释
--]]
02_变量.lua
print("****变量*****")
--[[
lua 中的简单的变量类型
lua 中所有的变量声明 都不需要声明变量类型 他会自动的判断类型
类似于c# 里面的var
lua 中的一个变量可以随便重复赋值
通过 type函数(返回值类型是string) 打印变量的类型
]]
--lua 中有8种数据类型
-- nul number string boolean
-- 函数 function
-- 表table
-- 数据结构 userdata
-- 协同程序 thread(线程)
-- nil 有点类似c#中的null
print("*****nil*****")
local null =nil
print(null)
print("null 的类型是 "..type(null));
-- number 所有的数字都是number
print("*****number*****")
local num= 10
print(num);
print("num 的类型是 "..type(num));
-- 字符串的声明 使用单引号或者双引号包裹
-- lua 中没有char 类型
print("*****string*****")
local str= "这里是字符串"
local str= '这里是字符串'
-- 上面两个都可以当做是字符串类型
print(str);
print("str 的类型是 "..type(str));
print("*****boolean*****")
local bool= true
-- 上面两个都可以当做是字符串类型
print(bool);
print("bool 的类型是 "..type(bool));
03_字符串操作.lua
print("******字符串********")
-- 中文字符在lua中占用3个长度
local str = "字符串"
-- 获取字符串的长度
print(#str);
local str2 ="abcdefg"
print(#str2)
print("******字符串多行打印********")
print("第一行\n第二行\n第三行")
local s =
[[
第一行
第二行
第三行
]]
print(s)
print("******字符串拼接********")
print("这里是通过".." ..".."进行字符串拼接")
-- %d 替换符号 表示与数值匹配占位
-- %s 替换符号 表示与字符匹配占位
-- %a 替换符号 表示与任何字符匹配
print(string.format("我今年%d岁了",27))
print("******别的类型转字符串********")
local a = true;
print(a);
print (tostring(a));
print("******字符串中提供的方法********")
str ="abCdefGh"
-- 小写转大写
print(string.upper(str))
-- 大写转小写
print(string.lower(str))
-- 翻转字符串
print(string.reverse(str))
-- 字符串所有查找
-- 返回值 3 5 代表第三个开始 到第5个
print(string.find(str,"Cde")) --3 5
-- 截取字符串
-- 从第三个开始截取
print(string.sub(str,3)) --CdefGh
--从第3个截取截取到第4个字符
print(string.sub(str,3,4)) --Cd
-- 字符串重复
-- 参数2 表示重复几次
print(string.rep(str,2))
-- 字符串修改 替换
print(string.gsub(str,"Cd","**"))-- ab**efGh 1 其中1 代表修改了几次
str ="abCdefGhCd"
print(string.gsub(str,"Cd","**")) --ab**efGh** 2
-- 字符转ASCII码
-- 参数1 代表指定位置的字符
local num = string.byte("Lua",1)
print(num)
--ASCII码转字符
print(string.char(num))
04_运算符.lua
print("*******运算符*****")
print("*******算数运算符*****")
-- + - / * / % ^(幂)
-- 字符串可以进行算数运算符运算
-- 没有自增运操作 会直接转成number
-- 没有复合运算符 += -= *= /=
print("加法运算符")
local a=1
local b= 2
print("a=1 b= 2 相加的结果是 a+b= "..a+b)
print("123"+1) -- 124 把3 直接+1
print("10.1"+1) -- 11.1 直接+1
print("减法运算"..1-2) -- -1
print("减法运算".."1"-2) -- -1
print("乘法运算"..2*3) --6
print("乘法运算".."2"*3) -- 6
print("除法运算"..6/2) -- 3.0
print("除法运算".."6" /2) -- 3.0
print("取余运算"..6%2) -- 0
print("取余运算".."6" %2) -- 0
print("取余运算"..7.5%2) -- 1.5
print("取余运算".."7.5" %2) --1.5
print("幂运算"..7.5^2) -- 56.25
print("取幂运算".."7.5" ^2) --56.25
print("*******条件运算符*****")
-- > < >= <= == ~=
print(" 3>1 ")
print(3>1)
print("3<1 ")
print(3<1)
print("3>=1 ")
print(3>=1)
print("3<=1 ")
print(3<=1)
print("3==1 ")
print(3==1)
print("3~=1 ")
print(3~=1)
print("*******逻辑运算符*****")
-- 与 或 非
-- c# 中 && || ! "可以出现短路情况"
-- lua中 and or not "可以出现短路情况"
print(true and false)
print (true or false)
print (not true)
print(false and print("123")) -- 123 不会打印 因为false 短路 不执行后面的语句
print("*******位运算符*****")
-- 位运算符 & |
print("*******三目运算符*****")
-- lua 中不支持三目运算符
-- c# 中 ? :
05_条件分支语句.lua
print("******条件分支语句*******")
-- 单分支
local a = 9
if a>5 then
print("单分支 if 语句执行")
end
-- 双分支
local a = 3
if a>5 then
print("双分支 if 语句执行")
else
print("双分支 else 语句执行")
end
-- 多分支
if a>5 then
print("多分支 if 语句执行")
elseif a>4 then
print("多分支 elseif 语句执行")
else
print("多分支 else 语句执行")
end
-- lua中没有switch 语法
06_循环.lua
print("*****循环语句*******")
print("*****while 循环语句*******")
local num =0
while num<5 do
print("while 循环中num 的值是 "..num)
num= num+1
end
print("*****do while 循环语句*******")
num =0;
repeat
print("repeat 循环中num的值是 "..num)
num=num+1
until num>=5 -- 满足天剑跳出 结束条件
print("*****for 循环语句*******")
-- 1初始值 5长度循环次数 1步长
for i = 1, 5, 1 do
print("for增量循环中i的的值是 ",i)
end
for i = 5, 1, -1 do
print("for减量循环中i的的值是 ",i)
end
07_函数.lua
print("*******函数********")
-- function 函数名()
-- end
-- a = function 函数名()
-- end
print("*******无参无返回值********");
-- 函数的两种定义方式
function F1()
print("F1函数")
end
F2 = function ()
print("F2函数")
end
F1();
F2();
print("*******有参********")
-- 有参数的函数定义
function F3(a,b)
print("F3函数");
end
F3(2,3);
print("*******有返回值********")
-- 有返回值的函数
function F4(a)
return a;
end
-- 多返回值函数
function F5()
return "参数1","参数2","参数3";
end
local f4 = F4("传入的参数 返回打印");
print("F4函数调用".. f4);
--多返回值函数
--f5_4 没有返回值 所以使用nil 自动补位
local f5_1,f5_2,f5_3,f5_4 = F5();
print(f5_1,f5_2,f5_3,f5_4);
print("*******函数的类型********")
F6 = function ()
print("函数F6函数");
end
F6();
-- 打印函数的类型
print(type(F6));
print("*******函数不支持重载********")
-- 函数的名相同,参数类型不同 或者参数个数不同
function F7()
print("函数的重载无参数调用")
end
function F7(a)
print("函数的重载一个参数调用")
end
-- 三个方法都会调用最后一个定义的函数
function F7(a,a)
print("函数的重载两个参数调用")
end
F7();
F7(1);
F7(1,2);
print("*******变长参数********")
function F8(...) -- 参数里面写三个点
arg={...} -- 相当于声明一个表 把参数放到表里面
-- 要使用变长参数需要使用一个表把参数存起来
for i = 1, #arg, 1 do -- #arg 是取表的长度
print(arg[i])
end
end
F8("参数1",2,"参数3")
print("*******函数嵌套********")
function F9 ()
return function ()
print ("F9 函数嵌套调用 ")
end
end
local f9 =F9();
f9();
function F10 ()
F11 =function ()
print ("F10 函数嵌套调用 ")
end
return F11
end
local f10 = F10()
f10()
print("*******闭包函数 面试的时候会问********")
function F12(x) -- x = 10
-- 改变传入参数的生命周期
return function (y) -- y =5
return x+y
end
end
local f12 = F12(10);
print(f12(5));
08_复杂数据类型表1.lua
print("*********复杂的数据类型表***********")
-- 所有的复杂类型都是table(表)
print("*********数组***********")
local tab= {1,2,3,"123",4,5,6,7,true,nil,8}
print(tab[1]);
print(tab[2]);
print(tab[4]);
print("*********数组的遍历***********")
for i = 1, #tab,1 do
print(tab[i])
end
-- 当nil 在最后会被忽略 不会打印
local tab= {1,2,3,"123",4,5,6,7,true,nil}
for i = 1, #tab,1 do
print(tab[i])
end
print("********二维数组***********")
local tab2 = {{1,2,3},{4,5,6}}
print(tab2[1][1])
print(tab2[2][1])
print("*********二维数组的遍历***********")
for i = 1, #tab2, 1 do
local tab2_tab = tab2[i]
for j = 1, #tab2_tab,1 do
print(tab2_tab[j])
end
end
print("*********自定义索引***********")
-- 有坑不要使用
local mytab = {[0]=1,2,3,[-1]=4,5}
print(#mytab) -- 遍历会有问题 0 和-1 无法识别
print(mytab[-1]) -- 指定会打印但是别坑自己 尽量别用
print(mytab[0])
local mytab = {[0]=1,[1]=6,[3]=2,[4]=3,[-1]=4,[5]=5}
print(#mytab) -- 真坑啊 因为数组中间断了
local mytab = {[1]=1,[2]=2,[3]=3,[5]=5,[7]=7}
print(#mytab)
print("遍历数组")
for i = 1, #mytab, 1 do
print(mytab[i])
end
09_迭代器遍历.lua
print("****迭代器遍历*****")
-- 迭代器遍历 主要来遍历表
-- #得到长度 其实并不准确,一般不要用#来遍历表
-- 只能找到连续的键 如果中间断了 也无法遍历后面的内容
local tab = {[0]= 1,2,[-1]=3,4,5}
-- ipairs遍历还是1开始往后遍历的 小于等于0 的值得不到
for index, value in ipairs(tab) do
print(index,value)
end
print("****ipairs遍历*****")
local tab = {[0]= 1,2,[-1]=3,4,5,[5]=6}
-- ipairs遍历还是1开始往后遍历的 小于等于0 的值得不到
for index, value in ipairs(tab) do
print(index,value)
end
print("****pairs遍历*****")
-- 他能够把所有的键都找到,通过键可以得到对应的值
for key, value in pairs(tab) do
print(key,value)
end
print("***迭代器只遍历键******")
for key in pairs(tab) do
print(key)
end
10_复杂数据类型表2.lua
print("********字典********")
print("********字典的声明********")
--字典是由键值对构成
local tab = {["name"]="张三",["age"]= 20,["1"] = 5}
-- 访问单个变量使用括号填键 来访问
-- 使用类似成员变量的形式来访问
print(tab.name);
print(tab["name"])
-- 这样写报错 虽然可以通过.成员变量形式得到值 但是不能是数字
--print(tab.1)
print(tab["1"])
-- 修改
tab.name = "李四"
print(tab.name)
-- 新增
tab["sex"] = "男"
print(tab.sex);
-- 删除 -- 删除不掉和空没什么区别
tab["sex"] =nil --nil
print(tab.sex);
print("********字典遍历********")
-- 什么也打印布出来 因为不能识别
for index, value in ipairs(tab) do
print(index,value);
end
-- 如果模拟字典 遍历一定用pairs
for key, value in pairs(tab) do
print(key,value) -- sex为空 会被忽略
end
print("****遍历key*****")
for key in pairs(tab) do
print(key)
end
print("****通过遍历key 得到值*****")
for key in pairs(tab) do
print(tab[key])
end
print("********类和结构体********")
-- lua 中 默认没有面向对象的 需要自己来实现
--成员变量 成员函数
Student ={
-- 成员变量
age=1,
sex ='男',
-- 成员函数
fuc = function ()
print("fuc函数")
end,
learn = function ()
print("学习函数")
end
}
-- c# 中使用累 实例化对象new 静态直接点出来
-- lua 中类的表现,更像是一个类中有很多静态变量和函数
print(Student.age)
Student.fuc()
-- 声明表过后在表外去声明表有的变量和方法
Student.name ="张三"
print(Student.name)
-- 第二种函数的声明
Student.Speak = function ()
print("说话")
end
Student.Speak();
-- 第三种函数的声明
function Student.Speak2()
print("说话2")
end
Student.Speak2();
Student2 ={
-- 成员变量
age=1,
sex ='男',
go = function ()
print("go函数调用")
end,
-- 成员函数
fuc = function (t)
-- 第二种 能够在函数内部调用自己属性或者方法的方法
-- 把自己做为一个参数传进来 在内部访问
print(t.sex)
print("fuc函数")
end,
learn = function ()
-- 这样写 这个age 和表中的age 没有任何关系他是一个全局变量
-- print(age);
-- 想要在表内部函数中 调用表本身的属性或者方法
-- 一定要指定是谁的 所以 表.属性 或者表名.方法
print(Student2.age)
print("学习函数")
end
}
function Student2:Speak2()
-- lua 中 有一个关键字self表示默认传入第一个参数
print("说话2 调用 :")
end
-- lua 中. 和: 调用的区别
-- : 调用方法 会默认把调用者做为参数传入方法中
Student2.learn();
-- 第一种调用方式
Student2.fuc(Student2);
-- 第二种调用方式
Student2:fuc();
print("********表的公共操作********")
-- 表中table 提供的一些公共方法
local tab1 = {{age = 1 ,name ="张三"},{age = 2 ,name = "李四"}}
local tab2 = {name = "王五",sex =true}
-- 插入
print(#tab1)
table.insert(tab1,tab2)
print(#tab1)
-- 删除
table.remove(tab1)
print(#tab1) -- 验证时候移除成功
-- 测试移除的是哪个
print(tab1[1].name) --张三 证明移除的是后面的
table.remove(tab1,1)
print(tab1[1].name) --李四 证明移除的是指定索引的元素 -- 剩下李四
local tab3 = {5,2,7,8,9,6,10}
-- 排序
-- 默认升序
table.sort(tab3);
for _, value in pairs(tab3) do
print("排序后的table" ..value)
end
-- 降序(排序规则函数)
table.sort(tab3,function (a,b)
if a>b then -- 这里填写的是规则
return true
end
end);
for _, value in pairs(tab3) do
print("排序后的table" ..value)
end
--拼接
local tab4 = {"123","456","789"}
-- 想要拼接的表 拼接字符
local str = table.concat(tab4,";")
print(str)
11_多lua脚本执行.lua
print("*****多lua脚本执行********")
print("*****全局变量和局部变量********")
A = 1 -- 全局变量
local a = 1 -- 局部变量
for i = 1, 2, 1 do
B = "全局变量"
end
print(B)
for i = 1, 2, 1 do
local b = "局部变量"
end
-- 局部变量
print(b) --nil
print("*****多脚本执行********")
-- 关键字 require("脚本名")
require("11_test") --只能加载一次 且 不支持中文
print(testA);
local testB= require("11_test") -- 另一种加载的方式(加载本地变量详见 11_test.lua 脚本最后一行)
print(testB);
print("*****脚本卸载********")
require("11_test") -- 无法重复加载
-- 关键字 package.loaded("脚本名")
arg = package.loaded["11_test"] -- 该脚本是否被加载
print(arg)
package.loaded["11_test"]= nil -- 卸载已经执行过得脚本
arg = package.loaded["11_test"]
print(arg)
local testB= require("11_test") -- 重新加载
print(testB);
print("*****大G表********")
-- _G 表是一个总表(table) 他将我们声明的所有的全局变量都存储在其中
--本地变量是不会存储到_G表中
for key, value in pairs(_G) do
print(key,value)
end
11_test.lua
print("测试")
testA = "123";
local testB = "456"
return testB -- require 另一种加载本地变量的方式调用
12_特殊用法.lua
print("*******特殊用法*********")
print("*******多变量赋值*********")
local a = 1
local b= true;
local c,d,e = 1,2,"多变量赋值"
print(a);
print(b);
print(c);
print(d);
print(e);
-- 多变量赋值 如果后面的值不够 会自动补孔
a,b,c = "重新赋值a","重新赋值b"
print(a);
print(b);
print(c); -- nul
-- 多变量赋值 如果后面的值多了 会自动丢弃
a,b,c = "赋值a","赋值b","赋值c","赋值d"
print(a);
print(b);
print(c);
print("*******多返回值*********")
-- 多返回值时 使用几个变量接 就有几个返回值
-- 如果少了 就少阶几个 如果多了 就自动补空
local function fuc()
return 10,20,30,40
end
a,b,c =fuc()
print(a);
print(b);
print(c);
a,b,c,d,e =fuc()
print(a);
print(b);
print(c);
print(d);
print(e);
print("*******and or*********")
-- 逻辑与 逻辑或
-- and or 不仅可以连接boolean 任何东西都可以用来连接
-- 在lua 中 只有nil 和false 才认为假
-- "短路" 对于and 来说 有假则假 对于or 来说有真则真
-- 所以 他们只需要判断第一个是否满足 就会停止计算了
print(1 and 2) -- 2
print( 0 and 1)
print( nil and 1)
print(false and 2)
print(true and 3)
print(true or 1)
print(false or 1)
print(nil or 1)
-- lua 不支持三目运算符
-- 模拟
local x =3
local y= 2
local res = (x>y) and x or y
return(res)
13_协程.lua
print("*******协程*********")
print("*******协程创建*********")
-- 第一种通过固定函数创建 常用方式
local function synccreate()
print("sync create 协程挂起函数")
end
local co1= coroutine.create(synccreate)
-- 协程本质是一个线程对象
print(co1)
print(type(co1));--thread
-- 第二种 coroutine,wrap()
local function syncwrap()
print("sync wrap 协程挂起函数")
end
local co2 =coroutine.wrap(syncwrap)
print(co2)
print(type(co2));--function
print("*******协程运行*********")
-- 第一种方式 对应的通过create 创建的协程
coroutine.resume(co1)
-- 第二种方式 对应的通过wrap 创建的协程
co2();
print("*******协程挂起*********")
local function syncloopcreate ()
while true do
print("sync loop create 协程挂起函数")
coroutine.yield()
end
end
local co3 = coroutine.create(syncloopcreate)
coroutine.resume(co3)
local function syncloopwrap()
while true do
print("sync loop wrap 协程挂起函数")
coroutine.yield()
end
end
local co4 = coroutine.wrap(syncloopwrap)
co4()
-- 第一个参数表示协程是否执行成功 第二个参数是返回值
local function syncloopcreatereturn()
local i =0;
while true do
i =i+1
print("sync loop wrap 协程挂起函数")
coroutine.yield(i)
end
end
local co5 = coroutine.create(syncloopcreatereturn)
local isOk,tempI= coroutine.resume(co5)
print(isOk,tempI) --true 1
local isOk,tempI= coroutine.resume(co5)
print(isOk,tempI)
local isOk,tempI= coroutine.resume(co5)
print(isOk,tempI)
-- 直接返回返回值 不会返回是否成功
local function syncloopwrapreturn()
local i =0;
while true do
i =i+1
print("sync loop wrap 协程挂起函数")
coroutine.yield(i)
end
end
local co6 = coroutine.wrap(syncloopwrapreturn);
print("wrap 函数返回值 "..co6())
print("wrap 函数返回值 "..co6())
print("wrap 函数返回值 "..co6())
print("*******协程状态*********")
-- coroutine.status(协程对象)
-- dead 结束
-- suspended 暂停
-- 进行中
coroutine.status(co1)
coroutine.status(co3)
-- 结束测试
print("co1 协程当前的状态是 ".. coroutine.status(co1))
-- 暂停测试
print("co3 协程当前的状态是 ".. coroutine.status(co3))
-- 进行中测试
local function sync()
local i =0;
while true do
i =i+1
print("co7 协程当前的状态是 "..coroutine.status(co7))
coroutine.yield(i)
end
end
co7 = coroutine.create(sync)
coroutine.resume(co7)
-- 这个函数可以得到当前正在运行的协程号
--coroutine.running()
local function sync1()
local i =0;
while true do
i =i+1
--
print(coroutine.running())--thread: 000001F0B63454C8 false
coroutine.yield(i)
end
end
local co8 = coroutine.create(sync1)
coroutine.resume(co8)
14_元表.lua
print("*********元表***********")
print("*********元表概念***********")
-- 任何表变量都可以做为另一个表变量的元表
-- 任何表变量都可以有自己的元表
-- 当我们字表中进行一些特定操作时
-- 会执行元表的内容
print("*********设置元表***********")
local meta ={}
local mytable ={}
-- 设置元表函数
-- 第一个参数子表 第二个参数 元表(父表)
setmetatable(mytable,meta)
print("*********特定操作***********")
print("*********元表操作 _tostring***********")
print("~~~~~~~mytable1~~~~~~~~")
local meta1 ={ }
local mytable1 ={}
-- 设置元表函数
-- 第一个参数 子表 第二个参数 元表(父表)
setmetatable(mytable1,meta1)
print(mytable1)
print("~~~~~~~mytable2~~~~~~~~")
local meta2 ={
-- 当子表要被做为字符串使用时 会默认调用这个元表中的tostring方法
__tostring =function ()
return "这里是元表"
end
}
local mytable2 ={}
-- 设置元表函数
-- 第一个参数 子表 第二个参数 元表(父表)
setmetatable(mytable2,meta2)
print(mytable2)
print("~~~~~~~mytable3~~~~~~~~")
local meta3 ={
__tostring =function (t)
return t.name;
end
}
local mytable3 ={
name = "这里是子表"
}
-- 设置元表函数
-- 第一个参数 子表 第二个参数 元表(父表)
setmetatable(mytable3,meta3)
print(mytable3)
print("*********元表操作 _call***********")
print("~~~~~~~mytable4~~~~~~~~")
local meta4 ={
__tostring =function (t)
return t.name;
end,
-- 当子表单过一个函数来使用时 会默认调用这个__call 的内容
__call =function ()
print("_call调用 ")
end
}
local mytable4 ={
name = "这里是子表"
}
-- 设置元表函数
-- 第一个参数 子表 第二个参数 元表(父表)
setmetatable(mytable4,meta4)
mytable4();
print("~~~~~~~mytable5~~~~~~~~")
local meta5 ={
__tostring =function (t)
return t.name;
end,
-- 当子表单过一个函数来使用时 会默认调用这个__call 的内容
__call =function (t)
print("_call调用 带有参数的")
print(t)
end
}
local mytable5 ={
name = "这里是子表"
}
-- 设置元表函数
-- 第一个参数 子表 第二个参数 元表(父表)
setmetatable(mytable5,meta5)
mytable5(1); -- 调用时 默认自己是第一个参数调用自己会调用__tostring
print("~~~~~~~mytable6~~~~~~~~")
local meta6 ={
__tostring =function (t)
return t.name;
end,
-- 当子表单过一个函数来使用时 会默认调用这个__call 的内容
-- 当希望传参数是 一定要记住 默认第一个参数 是调用自己(_-tostring)
-- 第二个参数才是传入的参数
__call =function (t,v)
print("_call调用 带有参数的")
print(t)
print(v)
end
}
local mytable6 ={
name = "这里是子表"
}
-- 设置元表函数
-- 第一个参数 子表 第二个参数 元表(父表)
setmetatable(mytable6,meta6)
-- 当子表当做函数使用 就会调用元表的 __call 方法
mytable6(1); -- 调用时 默认自己是第一个参数调用自己会调用__tostring
print("~~~~~~~mytable7~~~~~~~~")
--local mytes ={}
--mytes(); -- 接报错
print("*********元表-运算符重载***********")
local mytestmeta = {}
local mytesttable ={}
setmetatable(mytesttable,mytestmeta)
local mytest_table ={}
-- print(mytable8 + mytable9) 会报错 默认表是不能进行运算的
print("*********元表-运算符重载 + ***********")
local meta8 = {
-- 相当于运算符重载 当使用+ 运算符时会调用该方法
-- 运算符+
__add = function (t1,t2)
return t1.age + t2.age
end,
-- 运算符-
__sub =function (t1,t2)
return t1.age - t2.age
end,
-- 运算符*
__mul =function (t1,t2)
return t1.age * t2.age
end,
-- 运算符/
__div =function (t1,t2)
return t1.age / t2.age
end,
-- 运算符%
__mod =function (t1,t2)
return t1.age % t2.age
end,
-- 运算符^ 幂
__pow =function (t1,t2)
return t1.age ^ t2.age
end,
-- 运算符==
__eq =function (t1,t2)
return t1.age == t2.age
end,
-- 运算符<
__lt =function (t1,t2)
return t1.age < t2.age
end,
-- 运算符<=
__le =function (t1,t2)
return t1.age <= t2.age
end,
-- 运算符.. 拼接
__concat =function (t1,t2)
return t1.age .. t2.age
end
}
local mytable8 ={age = 3}
setmetatable(mytable8,meta8)
local mytable9 ={age = 4}
print(mytable8+mytable9)
print(mytable8-mytable9)
print(mytable8*mytable9)
print(mytable8/mytable9)
print(mytable8%mytable9)
print(mytable8^mytable9)
-- 如果要用条件运算符来比较两个对象
-- 这两个对象的元表一定要一致 才能准确调用方法
print("mytable8==mytable9")
print(mytable8==mytable9)
setmetatable(mytable9,meta8)
print(mytable8==mytable9)
print(mytable8<mytable9)
print(mytable8<=mytable9)
print(mytable8..mytable9)
print("*********元表 _index 和 _newindex***********")
local meta10 ={}
local mytable10 ={}
setmetatable(mytable10,meta10)
-- __index 当子表中找不到某个属性时
-- 回到元表中 __index 指定的表去找索引
print(mytable10.age) --nil
local meta11 ={
age =20
}
local mytable11 ={}
setmetatable(mytable11,meta11)
-- __index 当子表中找不到某个属性时
-- 回到元表中 __index 指定的表去找索引
print(mytable11.age) --nil
local meta12 ={
-- 写法一
__index ={age =10}
}
-- 写法二
local mytable12 ={}
setmetatable(mytable12,meta12)
-- __index 当子表中找不到某个属性时
-- 回到元表中 __index 指定的表去找索引属性
print(mytable12.age) --nil
local meta13 ={
age =20
}
-- 写法二
meta13.__index =meta13
local mytable13 ={}
setmetatable(mytable13,meta13)
-- __index 当子表中找不到某个属性时
-- 回到元表中 __index 指定的表去找索引属性
print(mytable13.age) --nil
-- 有坑
meta14 ={
age =30,
__index =meta14
}
local mytable14 ={}
setmetatable(mytable14,meta14)
-- __index 当子表中找不到某个属性时
-- 回到元表中 __index 指定的表去找索引属性
print(mytable14.age) --nil
-- 套娃写法
local meta15Father={ age =40}
meta15Father.__index = meta15Father;
local meta15 ={}
meta15.__index =meta15
setmetatable(meta15,meta15Father)
local mytable15 ={}
setmetatable(mytable15,meta15)
-- __index 当子表中找不到某个属性时
-- 回到元表中 __index 指定的表去找索引属性
print(mytable15.age) --nil
-- newindex 当赋值时,如果赋值一个不存在的索引
-- 那么会吧这个值赋值到newindex 所致的表中不会修改自己
local meta16 ={}
local mytable16 ={}
setmetatable(mytable16,meta16);
mytable16.age = 17 -- 在表中添加了一个age属性= 17
print(mytable16.age)
local meta17 ={}
meta17.__newindex = {} -- 重定向 index
local mytable17 ={}
setmetatable(mytable17,meta17);
mytable17.age = 18
print(mytable17.age)
print(meta17.__newindex.age)
-- 获取元表
print(getmetatable(mytable17))
--回去找自己身上有没有这个变量
print(rawget(mytable17,"age"))
-- 该方法忽略newindex 的设置 智慧改自己的变量
print(rawset(mytable17,"age",2))
print(mytable17.age)
16_面向对象.lua
print("**********面向对象***********")
print("**********封装***********")
-- 面向对象 lei 都是基于table 来实现的
local Object = {}
Object.id =1
function Object:test()
print("test方法调用")
print(self.id)
end
-- 冒号 是会自动将调用这个函数的对象 做为第一个参数传入方法
function Object:new()
-- self 代表是 我们迷人传入的第一个参数
-- 对象就是变量 返回一个新的变量
-- 返回出去的内容 本质上就是表的对象
local obj ={}
-- 元表知识 __nbdex 当找自己的变量 找不到时 就会取找元表当中的 __index指向的内容
self.__index=self
setmetatable(obj,self)
return obj
end
local myobj = Object:new()
print(myobj)
print(myobj.id)
myobj:test()
myobj.id =5 -- 不会改变Object id
print(myobj.id) --5
print(Object.id) -- 1
myobj.__index.id =3 -- 赋值有效 会改变Object id
print(myobj.id) --5
print(Object.id) --3
myobj:test() -- 5 打印的是myobj 里面的id 因为传入的是myobj
print("**********继承***********")
-- c# 中 类名:继承类
-- 写一个用于继承的方法
function Object :subClass(className)
-- _G 知识点 是总表 所有声明的全局变量 都以键值对的形式存在其中
_G[className]={}
-- 写相关继承的规则
-- 用到元表
local obj =_G[className]
self.__index=self
-- 子类 定义一个base 属性 base 属性代表父类
obj.base= self
setmetatable(obj,self)
end
Object:subClass("Person")
print(Person)
print(Person.id)
local p1= Person:new()
print(p1.id)
Object:subClass("Monster")
local m1=Monster:new()
print(m1.id)
m1:test()
print("**********多态***********")
-- 相同行为 不同表现 就是多态
-- 相同方法 不同执行逻辑 就是多态
Object:subClass("GameObject")
GameObject.posx = 0;
GameObject.posy =0;
function GameObject:Move()
self.posx=self.posx+1;
self.posy=self.posy+1;
print(self.posx);
print(self.posy);
end
GameObject:subClass("Player")
function Player:Move()
print("Player Move 调用父类方法")
-- base 指的是GameObjec 表(类)
-- 这种方式调用相当于把基类表做为第一个参数传入到方法中
-- 避免把基类表 传入到方法中 这样相当于就是公用一张表属性
--self.base:Move()
-- 如果要执行父类逻辑 我们不要使用冒号调用
-- 改用 点 调用 然后自己传入第一个参数
self.base.Move(self)
end
local p1= Player:new()
p1:Move()
--
local p2= Player:new()
p2:Move()
17_自带库.lua
print("********自带库**********")
-- string
-- table
print("********时间相关自带库**********")
-- 系统时间
print(os.time())
-- 自己传入参数得到时间
print(os.time({year =2014,month =8,day =14,hour = 0,min = 0,sec = 0}))
-- 利用os 的date("*t")
local nowtime = os.date("*t")
print(nowtime)
for key, value in pairs(nowtime) do
print(key,value)
end
print(nowtime.hour)
print("********数学运算相关自带库**********")
-- math
-- 绝对值
print(math.abs(-11))
-- 弧度转角度
print(math.deg(math.pi))
-- 三角函数(传入弧度)
print(math.sin(math.pi))
print(math.cos(math.pi))
-- 向下向上取整
print(math.floor(2.6))
print(math.ceil(5.2))
-- 最大值最小值
print(math.max(1,2))
print(math.min(4,5))
-- 把小数 分离成整数部分和小数部分
print(math.modf(1.2))
-- 随机数
-- 先设置随机数种子
math.randomseed(os.time())
print(math.random(100))
-- 开方
print(math.sqrt(4))
print("********路径相关自带库**********")
-- lua 脚本加在路径
print(package.path)
package.path = package.path..";C:\\"
print(package.path)
18_垃圾回收.lua
print("****** 垃圾回收*********")
test={id = 1,name="12321313"}
-- 垃圾回收关键字
-- collectgarbage
-- 获取当前lua 占用内存数 k字节
-- 用返回值*1024 就可以得到具体占用字节数
print(collectgarbage("count"))
-- lua 中的机制和C# 中垃圾回收机制很相似 解除羁绊 就会变成垃圾
test =nil
-- 进行垃圾回收
collectgarbage("collect")
print(collectgarbage("count"))
-- lua 中 有自动定时进行GC的方法
-- Unity 中热更新开发 尽量不要去用自动垃圾回收
面向对象类封装继承多态代码
-- 面向对象实现
-- 万物之父 多有对象基类 Object
-- 封装
Object ={}
function Object:new()
local obj= {}
-- 给空对象设置元素 以及__index
self.__index =self;
setmetatable(obj,self);
return obj;
end
-- 继承
function Object:subClass(className)
-- 根据名字生成新表(类)
_G[className]={}
local obj = _G[className]
-- 设置自己的父类
obj.base=self;
-- 给子类设置元表 以及__index
self.__index =self;
setmetatable(obj,self);
end
-- 声明一个新的类
Object:subClass("GameObject")
-- 成员变量
GameObject.posx =0
GameObject.posy = 0
-- 成员方法
function GameObject:Move()
self.posx =self.posx+1
self.posy =self.posy+1
end
-- 实例化对象
local obj =GameObject:new()
print(obj.posx);
obj:Move()
print(obj.posx)
local obj2 =GameObject:new()
print(obj2.posx);
obj2:Move()
print(obj2.posx)
print("***************")
-- 多态
-- 声明一个新的类 Player 继承GameObject
GameObject:subClass("Player")
-- Move 方法
function Player:Move()
self.base.Move(self)
end
-- 实例化Player 对象
local p1 = Player:new()
print(p1.posx)
p1:Move()
print(p1.posx)
local p2 = Player:new()
print(p2.posx)
p2:Move()
print(p2.posx)