学习lua 笔记

本文介绍了Lua编程的基础知识,包括Hello World、变量、字符串操作、运算符、条件分支语句、循环、函数、复杂数据类型(如表)以及迭代器的使用。此外,还讲解了全局变量与局部变量、多脚本执行、元表的概念及其应用。通过实例展示了如何在Lua中实现面向对象编程,如封装、继承和多态。最后,简要提到了Lua的垃圾回收机制。
摘要由CSDN通过智能技术生成

学习lua 笔

学习视频连接
首先 感谢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)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值