热更新解决方案2 —— Lua语法相关知识点
概述


开发环境搭建




Lua语法

1.第一个Lua程序


2.变量

print("******变量*******");
--lua当中的简单变量类型
-- nil number string boolean
-- lua 中所有的变量声明 都不需要声明变量类型 它会自动的判断类型
-- 类似C# 中的var
--lua中的一个变量 可以随便赋值 —— 自动识别类型--通过type 函数 我们可以得到变量的类型
-- type 的返回值是 string--lua中使用没有声明过的变量
--不会保错 默认值 是nil
print(b)--nil 有点类似 C#中的null
print("******nil*******");
a = nil
print(a)
print(type(a))
print(type(type(a)))--number 所有的数据都是number
print("*******number*******")
a = 1
print(a)
a = 1.2
print(a)
print(type(a))print("*******string*******")
a = "123"
print(a);
print(type(a))
--字符串的声明,使用单引号或者双引号包裹
--lua里 没有char
a = '123'
print(a)
print(type(a))print("*******boolean*******")
a = true
print(a)
a = false
print(a)
print(type(a))--复杂数据类型
--函数 function
--表 table
--数据结构 userdata
--协同程序 thread(线程)

3.字符串操作

print("******字符串*******")
str = "双引号字符串"
str = '单引号字符串'--获取字符串的长度
print("*******字符串长度**********")
s = "Sun木兮"
--一个汉字占3个长度
--英文符号 占1个长度
print(#s)print("*******字符串多行打印*******")
--方式一
--lua中也是支持转义字符的
print("123\n123")--方式二
s = [[山有
木兮
木有
枝]]
print(s)
print([[心悦
君兮君]])print("*******字符串拼接*******")
--方式一
--字符串拼接 通过..
print("123" .. "456")
s1 = "111"
s2 = 222
print(s1 .. s2)
s1 = 111
s2 = 222
print(s1 .. s2)--方式二
print(string.format("山有木兮, 木%d", 67))
--%d: 与数字拼接
--%a: 与任何字符串拼接
--%s: 与字符串配对
--...print("*******别的类型转字符串*******")
a = true;
print(tostring(a))print("*******字符串提供的公共方法*******")
str = "abCdeFg"
--小写转大写的方法
--该方法不会改变原字符串,之后返回一个新字符串 (string大部分都不会改变原字符串)
print(string.upper(str))
print(str)
--大写转小写
print(string.lower(str))
--翻转字符串
print(string.reverse(str))
--字符串索引查找
print(string.find(str, "Cde")) --3 5
print(string.find(str, "C")) -- 3 3
--截取字符串
print(string.sub(str, 3)) --CdeFg
print(string.sub(str, 3, 4)) --重载方法
--重复字符串
print(string.rep(str, 1)) --返回的是原字符串
print(string.rep(str, 2)) --abCdeFgabCdeFg 返回两遍字符串
--字符串修改
print(string.gsub(str, "Cd", "**")) -- 返回 ab**eFg 1 1代表修改的次数
str = "abCdeFgCd"
print(string.gsub(str, "Cd", "**")) -- 返回 ab**eFg** 2--字符转 ASCII码
a = string.byte("Lua", 1) --将字符串里的一个指定位置转为ASCII码
print(a)
--ASCII码 转字符
print(string.char(a))

4.运算符

print("*******运算符********")print("*******算术运算符********")
-- 只有 + - * / % ^(幂运算)
-- 没有自增自减 ++ --
-- 没有复合运算符 += -= /= *= %=
-- 字符串 可以进行 算数运算符操作 会自动转成 number--加法
print("加法运算" .. 1 + 2)
a =1
b = 2
print(a + b)
print("123" + 1) -- 输出:124
print("123.4" + 1) -- 输出:124.4--减法
print("减法运算" .. 1 - 2) -- 输出 -1
print("123.4" - 1) -- 输出: 122.4--乘法
print("乘法运算" .. 1 * 2)
print("123.4" * 2) -- 246.8--除法
print("除法运算" .. 1 / 2) -- 0.5
print("123.4" / 2) -- 61.7--取余
print("取余运算" .. 1 % 2) -- 1
print("123.4" % 2) -- 1.4--幂运算
-- ^ 在lua中 该符号是幂运算 而在C#中^是异或
print("幂运算" .. 2 ^ 5)
print("123.4" ^ 2)print("*******条件运算符********")
-- > < >= <= == ~=(不等于,C#中是!=)
print(3>1)
print(3<1)
print(3>=1)
print(3>=1)
print(3==1)
print(3~=1)print("*******逻辑运算符********")
-- 逻辑与 C#中 && 逻辑或 C#中 || 取反 C#中 !
-- Lua中 与:and 或:or 非:not 在lua中and、or也支持短路
print(true and false) -- false
print(true and true) -- tureprint(true or false) -- true
print(false or false) -- falseprint(not true) -- falseprint("********短路测试*********")
print(false and print("123")) -- 输出 false
print(true and print("123")) -- 输出: 123 nilprint("*******位运算符********")
-- & | lua中不支持位运算符 需要我们自己实现print("*******三目运算符********")
-- lua中也不支持三目运算符

5.条件分支语句

print("***********条件分支语句************")
a = 9
-- if 条件 then...end
--单分支
if a > 5 thenprint("124")
end--双分支
--if 条件 then...else...end
if a < 5 thenprint("123")
elseprint("321")
end--多分支
--if 条件 then...elseif 条件 then...elseif 条件 then...else...end
if a < 5 thenprint("123")
--lua中 elseif 一定是连着写的 否则会报错
elseif a == 6 thenprint("6")
elseif a == 7 thenprint("7")
elseif a == 8 thenprint("8")
elseif a == 9 thenprint("9")
elseprint("other")
end-- 组合条件的使用
if a >= 3 and a <= 9 thenprint("3到9之间")
end-- Lua中没有switch 需要的话可以自己实现
6.循环



7.函数

print("********函数*******")
--function 函数名()
--end--a = function()
--endprint("********无参数无返回值*******")
-- F1() -- 不能在一个函数声明之前去调用它
function F1()print("Fi函数")
end
F1()-- 有点类似 C#中 委托和事件
F2 = function()print("F2函数")
end
F2()print("********有参数*******")
function F3(a)print(a)
end
F3(1)
F3("123")
F3(true)
-- 如果你传入的参数 和函数参数个数不匹配
-- 它不会报错 只会补空nil 或者丢弃
F3()
F3(1,2,3)print("********有返回值*******")
function F4(a)return a, "123", true
end
-- 多返回值时 在前面声明多个变量来接即可
-- 如果变量不够 不影响 值会接取对应位置的返回值
-- 如果变量多了 也不影响 多出的直接赋值nil
temp, temp2, temp3 = F4("1")
print(temp)
print(temp2)
print(temp3)print("********函数的类型*******")
-- 函数类型 就是 function
F5 = function()print("123")
end
print(type(F5))print("********函数的重载*******")
--函数名相同 参数类型不同 或者参数个数不同
--luaz中 函数不支持重载
--默认调用的是最后一个申明的这个函数
function F6()print("F6_1")
end
function F6(str)print(str)
endF6() -- 输出 ilprint("********变长参数*******")
function F7(...)--变长参数使用 用一个表存起来 再用arg = {...}for i = 1,#arg doprint(arg[i])end
end
F7(1,"123",true,4,5,6,7)print("********函数嵌套*******")
--function F8()
-- F9 = function()
-- print("123")
-- end
-- return F9
--end-- 简洁写法
function F8()return function()print("123")end
endf9 = F8()
f9()--Lua 中闭包的体现
function F9(x)--改变传入参数的生命周期return function(y)return x + yend
endf10 = F9(10)
print(f10(5))

8.复杂数据类型 —— 表

print("*********复杂数据类型 table***********")
--所有的复杂类型都是table(表)print("*********数组***********")
a = {1,2,3,4,"1231",true,nil}
--lua中 索引从1开始
print(a[0]) -- 输出 nil 超出索引不会报错
print(a[1]) -- 输出 1
print(a[5])
print(a[6])
print(a[7])
--# 是通用的获取长度的关键字
--在打印长度的时候 空被忽略
--如果表中(数组中)某一位变成nil 会影响#获取的长度
print(#a) -- 输出 6 第7位是nil所以会被忽略
--a = {1,2,nil,4,"1231",true,nil}
--print(#a) -- 输出 2print("*********数组的遍历***********")
for i = 1,#a doprint(a[i])
endprint("*********二维数组***********")
--注意 其实lua中是没有二维数组的概念的 只是我们用表体现出数组、二维数组、字典的特征
a = {{1,2,3},{4,5,6}}
print(a[1][1]) -- 第一个表
print(a[1][2])
print(a[1][3])
print(a[2][1]) -- 第二个表
print(a[2][2])
print(a[2][3])print("*********二维数组的遍历***********")
for i = 1,#a dob = a[i]for j = 1,#b doprint(b[j])end
endprint("*********自定义索引***********")
-- 不建议自定义索引
aa = {[0] = 1,2,3, [-1] = 4,5}
print(aa[0])
print(aa[-1])
print(aa[1])
print(aa[2])
print(aa[3])
print(#aa)

9.迭代器遍历



10.复杂数据类型 —— 表

字典

print("*************复杂数据类型——表2*****************")
print("******字典*****")
print("******字典的申明*********")
--字典是由键值对构成
a = {["name"] = "Sunset", ["age"] = 19, ["1"] = 5}
--返回单个变量 用中括号填键 来访问
print(a["name"])
print(a["age"])
print(a["1"])
--还可以类型 .成员变量 的形式得到值
print(a.name)
print(a.age)
-- 虽然可以通过,成员变量的形式得到值 但是不能是数字
--print(a.1)
--字典修改
a["name"] = "Sunrise"
print(a["name"])
print(a.name)
--字典新增
a["sex"] = false
print(a["sex"])
print(a.sex)
--字典删除 其实就是置空
a.sex = nil
print(a["sex"])
print(a.sex)print("************字典的遍历***********")
--如果要模拟字典遍历 一定用 pairs
for k,v in pairs(a) doprint(k,v)
end
-- 可以只得键
for k in pairs(a) doprint(k)print(a[k])
endfor _,v in pairs(a) doprint(v)
endprint("**********类和结构体************")print("**********表的公共操作**********")

类

print("**********类和结构体************")--Lua中是默认没有面向对象的 需要我们自己来实现
-- 成员变量 成员函数...
Student = {--年龄age = 1,--性别sex = true,--成长函数Up = function()-- 这样写 这个age 和表中的age没有任何关系 它是一个全局变量--print(age) -- 会输出 nil 而没有输出 1--想要在表内部函数中 调用表本身的属性或者方法--一定要指定是谁的 所以要使用得 表名.属性 或者 表名.方法print(Student.age) -- 输出 1print("成长中")end,--学习函数Learn = function(t)-- 第二种 能够在函数内部调用自己属性或者方法的 方法-- 把自己作为一个参数传进来 在内部访问print(t.sex)print("学习中")end
}--Lua中 .和冒号 的区别
Student.Learn(Student)
--冒号调用方法 会默认把调用者 作为第一个参数传入方法中
Student:Learn()--声明表过后 在表外去声明表有的变量和方法
Student.name = "Sunset"
Student.Speak = function()print("说话")
end
-- 函数的第三种申明方式
function Student:Speak2()--lua中 有一个关键字 self表示 默认传入的第一个参数print(self.name .. "说话2")
end
--C#中要使用类 实例化对象new 静态直接点
--Lua中的类的表现 更新是一个类中有很多 静态变量和函数
print(Student.age)
print(Student.name)
Student.Up()
Student.Speak()
Student:Speak2()
Student.Speak2(Student)

表的公共操作

print("**********表的公共操作**********")
--表中 table提供的一些公共方法的讲解t1 = {{age = 1, name = "123"}, {age = 2, name = "345"}}t2 = {name = "Sunset", sex = true}print("********插入********")
--插入
print(#t1)
table.insert(t1, t2)
print(#t1)
print(t1[1]) -- 打印出的是地址
print(t1[2])
print(t1[3])
print(t1[3].sex)print("********删除********")
--删除指定元素
--remove方法 传表进去 会移除最后一个索引的内容
table.remove(t1)
print(#t1)
print(t1[1].name)
print(t1[2].name)
print(t1[3])--remove方法 传两个参数 第一个参数 是要移除内部的表
--第二个参数 是要移除内容的索引
table.remove(t1, 1)
print(t1[1].name)
print(#t1)print("********排序********")
t2 = {5,3,7,4,1,2}
--传入要排序的表 默认 升序排序
table.sort(t2)
for _,v in pairs(t2) doprint(v)
end
print("********排序自定义升降********")
--传入两个参数 第一个是用于排序的表
--第二个是 排序规则函数
table.sort(t2, function(a,b) -- 降序if a > b thenreturn trueend
end)
for _,v in pairs(t2) doprint(v)
endprint("**********拼接********") -- 了解即可
tb = {"123", "456", "789", "10"}
--连接函数 用于拼接表中元素 返回值 是一个字符串 大部分只能拼接字符串
str = table.concat(tb, ";")
print(str)

11.多Lua脚本执行

print("**************多脚本执行***********")
print("**************全局变量和本地变量***********")
--目前为止我们申明的变量都是 全局变量
a = 1
b = "123"for i=1,2 doc ="Sunset"
end
print(c)--本地(局部)变量的关键字 local
for i=1,2 dolocal d = "Sunset"print("循环中的d"..d)
end
print(d)fun = function()tt = "123123" --所以如果要让它是局部变量就要加 local
end
fun()
print(tt) -- 在没有执行fun() 之前 会返回nil,fun()执行后就变全局变量了-- 只能在自己脚本用的变量
local tt2 = "666"print("**************多脚本执行***********")
--关键字 require("脚本名") require('脚本名')
require("Test") -- 打印 Test测试 456
print(testA) -- 打印 123
print(testLocalA) -- 打印不出 另一个脚本的本地变量print("**************脚本卸载***********")
--如果是require加载执行的脚本 加载一次过后就不会再被执行
require('Test')
--package.loaded["脚本名"]
--返回值是 boolean 意思是 该脚本是否被执行
print(package.loaded["Test"])
--卸载已经执行过的脚本
package.loaded["Test"] = nil;
print(package.loaded["Test"])
--require("Test")--require 执行一个脚本时 可以在脚本最后返回一个外部希望获取的内容
local testLA = require("Test")
print(testLA)print("**************大G表***********")
-- _G 表是一个总表(table)它将我们申明的所有全局变量都存储在其中
for k,v in pairs(_G) doprint(k,v)
end
-- 本地变量 加了local的变量是不会存储到_G表中的

12.特殊用法

print("********特殊用法*********")print("********多变量赋值*********")
a,b,c = 1,2,"123"
print(a)
print(b)
print(c)
--多变量赋值 如果后面的值不够 会自动补空
a,b,c = 1,2
print(a)
print(b)
print(c)
--多变量赋值 如果后面的值多了 会自动省略
a,b,c = 1,2,3,4,5
print(a)
print(b)
print(c)print("********多返回值*********")
function Test()return 10,20,30,40
end
--多返回值时 用几个变量接 就有几个值
--如果少了 就会少接几个 如果多了 就会自动补空
a,b,c = Test()
print(a)
print(b)
print(c)a,b,c,d,e = Test()
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) -- 1
print(nil and 1) -- nul
print(false and 2) -- false
print(true and 3) -- 3print(true or 1) -- true
print(false or 1) -- 1
print(nil or 2) -- 2
print(1 or 2) -- 1--Lua不支持三目运算符 (但是我可以靠and or 模拟出三目运算符来)
x = 3
y = 2
local res = (x > y) and x or y
print(res)

13.协程

print("**********协同程序************")print("**********协程的创建************")
-- 常用方式
--coroutine.create()
fun = function()print(123)
end
co = coroutine.create(fun)
--协程的本质是一个线程对象
print(co) -- 返回 thread 地址
print(type(co)) -- 返回类型 thread 线程--coroutine.wrap()
co2 = coroutine.wrap(fun)
print(co2)
print(type(co2)) -- 返回的 是 function 函数类型print("**********协程的运行************")
--第一种方式 对于的 是通过 create创建的协程
coroutine.resume(co)
--第二种方式
co2()print("**********协程的挂起************")
fun2 = function()local i = 1while true doprint(i)i = i + 1--协程的挂起函数coroutine.yield(i)print(coroutine.status(co3))print(coroutine.running())end
endco3 = coroutine.create(fun2)
--默认第一个返回值 是 协程是否启动成功
--第二个返回值是 yield里面的返回值
isOk, tempI = coroutine.resume(co3)
print(isOk, tempI)
isOk, tempI = coroutine.resume(co3)
print(isOk, tempI)
isOk, tempI = coroutine.resume(co3)
print(isOk, tempI)co4 = coroutine.wrap(fun2)
--co4()
--co4()
--co4()
--这种方式的协程 也可以有返回值 只是没有默认第一个返回值了
print("返回值:"..co4())
print("返回值:"..co4())
print("返回值:"..co4())print("**********协程的状态************")
-- coroutine.status(协程对象)
-- dead 结束
-- suspended 暂停
-- running 进行中
print(coroutine.status(co3))
print(coroutine.status(co))--这个函数可以得到当前正在 运行的协程的线程号
print(coroutine.running())

14.元表
注:知识点较多要配合视频复习

print("************元表**********")
print("************元表概念**********")
--任何表变量都可以作为另一个表变量的元表
--任何表变量都可以有自己的元表(父)
--当我们子表中进行一些特定操作时
--会执行元表中的内容
print("************设置元表**********")
meta = {}
myTable = {}
--设置元表函数
--第一个参数 子表
--第二个参数 元表(父)
setmetatable(myTable, meta)print("************特定操作**********")
print("************特定操作-__tostring**********")
meta2 = {-- 当子表要被当做字符串使用时 会默认调用这个元表中的tostring方法__tostring = function(t) -- tostring 前面有两条下划线return t.nameend
}
myTable2 = {name = "Sunset2"
}
setmetatable(myTable2, meta2)
print(myTable2) --输出 Sunset2print("************特定操作-__call**********")
meta3 = {-- 当子表要被当做字符串使用时 会默认调用这个元表中的tostring方法__tostring = function(t) -- tostring 前面有两条下划线return t.nameend,--当子表被当做一个函数来使用时 会默认调用这个 __call中的内容--当希望传参数时 一定要记住 默认第一个参数 是调用者自己__call = function(a, b)print(a)print(b)print("山有木兮")end
}
myTable3 = {name = "Sunset2"
}
setmetatable(myTable3, meta3)
--把子表当做函数使用 就会调用元表的 __call方法
myTable3(1) -- 输出 Sunset2 1 山有木兮print("************特定操作-运算符重载**********")meta4 = {--相当于运算符重载 当子表使用+运算符时 会调用该方法--运算符+__add = function(t1, t2)return t1.age + t2.ageend, -- 记得打逗号 不然会报错--运算符-__sub = function(t1, t2)return t1.age - t2.ageend,--运算符 *__mul = function(t1, t2)return t1.age * t2.ageend,--运算符 /__div = function(t1, t2)return t1.age / t2.ageend,--运算符 %__mod = function(t1, t2)return t1.age % t2.ageend,--运算符 ^__pow = function(t1, t2)return t1.age ^ t2.ageend,--运算符 ==__eq = function(t1, t2)return t1.age == t2.ageend,--运算符 <__lt = function(t1, t2)return falseend,--运算符 <=__le = function(t1, t2)return tureend,--运算符 ..__concat = function(t1, t2)return "567"end,}
myTable4 = {age = 1}
setmetatable(myTable4, meta4)
myTable5 = {age= 2}
setmetatable(myTable5, meta4)print(myTable4 + myTable5)
print(myTable4 - myTable5)
print(myTable4 * myTable5)
print(myTable4 / myTable5)
print(myTable4 % myTable5)
print(myTable4 ^ myTable5)--如果要用条件运算符 来比较两个对象
--这两个对象的元表一定要一致 才能准确调用方法
print(myTable4 == myTable5)
print(myTable4 < myTable5)
print(myTable4 <= myTable5)
print(myTable4 .. myTable5)print("************特定操作-__index和__newIndex**********")meta6Father = {age = 1
}
meta6Father.__index = meta6Fathermeta6 = {--age = 1--__index = {age = 1}
}
--__index 的赋值 写在外面来初始化
meta6.__index = meta6
--meta6.__index = {age = 1}myTable6 = {}
setmetatable(meta6, meta6Father)
setmetatable(myTable6, meta6)
--得到元表的方法
print(getmetatable(myTable6))-- __index 当子表中 找不到某一个属性时
-- 会到元表中 _index指定的表去找属性
print(myTable6.age)
--rawget 当我们使用它时 会去找自己身上有没有这个变量
--myTable6.age = 6
print(rawget(myTable6, "age"))-- __newIndex 当赋值时,如果赋值一个不存在的索引
-- 那么会把这个值赋值到newindex所指的表中 不会修改自己
meta7 = {}
meta7.__newindex = {}
myTable7 = {}
setmetatable(myTable7, meta7)
myTable7.age = 7
print(myTable7.age)
print(meta7.__newindex.age)
--rawset 该方法 会忽略newindex的设置 只会改自己的变量
rawset(myTable7, "age", 2)
print(myTable7.age)

15.面向对象

封装

print("**********面向对象****************")
print("**********封装****************")
--面向对象 类 其实都是基于 table来实现
--也会元表相关的知识点
Object = {}
Object.id = 1function Object:Test()print(self.id)
end-- 完成 new 对象的操作
-- 冒号 是会自动将调用这个函数的对象 作为第一个参数传入的写法
function Object:new()--self 代表的是 我们默认传入的第一个参数--对象就是变量 返回一个新的变量--返回出去的内容 本质就是表对象local obj = {}--元表知识 __index 当找自己的变量 找不到时 就会去找元素中_index指向的内容self.__index = selfsetmetatable(obj, self)return obj
endlocal myObj = Object:new()
print(myObj)
print(myObj.id)
myObj:Test()
--对空表中 申明一个新的属性id,不会改变元表中的
myObj.id = 2
-- 总结一下:找的到就用自己的,找不到就用别人的,谁调用用谁的self
print(Object.id) -- 还是输出 1
myObj:Test() -- 这里会输出 2print("**********继承****************")print("**********多态***************")
继承

print("**********面向对象****************")
print("**********封装****************")
--面向对象 类 其实都是基于 table来实现
--也会元表相关的知识点
Object = {}
Object.id = 1function Object:Test()print(self.id)
end-- 完成 new 对象的操作
-- 冒号 是会自动将调用这个函数的对象 作为第一个参数传入的写法
function Object:new()--self 代表的是 我们默认传入的第一个参数--对象就是变量 返回一个新的变量--返回出去的内容 本质就是表对象local obj = {}--元表知识 __index 当找自己的变量 找不到时 就会去找元素中_index指向的内容self.__index = selfsetmetatable(obj, self)return obj
endlocal myObj = Object:new()
print(myObj)
print(myObj.id)
myObj:Test()
--对空表中 申明一个新的属性id,不会改变元表中的
myObj.id = 2
-- 总结一下:找的到就用自己的,找不到就用别人的,谁调用用谁的self
print(Object.id) -- 还是输出 1
myObj:Test() -- 这里会输出 2print("**********继承****************")
--C# class 类名 : 继承类
--写一个用于继承的方法
function Object:subClass(className)-- _G知识点 是总表 所有声明的全局标量 都以键值对的形式存在其中_G[className] = {}--写相关继承的规则--要用到元表local obj = _G[className]self.__index = selfsetmetatable(obj, self)
endObject:subClass("Person")
--print(Person)
--print(Person.id)local p1 = Person:new()
print(p1.id) -- 还是打印的 Object 的 id 1
p1.id = 100
print(p1.id)
p1:Test()Object:subClass("Monster")
local m1 = Monster:new()
print(m1.id)
m1.id = 200
print(m1.id)
m1:Test()-- 补充 _G 的一些其他用法
--print(_G) --输出 table 加 地址 _G本质也是一张表
--_G["a"] = 1
--_G.b = "123"
--print(a) -- 1
--print(b) -- 123print("**********多态***************")
多态

print("**********面向对象****************")
print("**********封装****************")
--面向对象 类 其实都是基于 table来实现
--也会元表相关的知识点
Object = {}
Object.id = 1function Object:Test()print(self.id)
end-- 完成 new 对象的操作
-- 冒号 是会自动将调用这个函数的对象 作为第一个参数传入的写法
function Object:new()--self 代表的是 我们默认传入的第一个参数--对象就是变量 返回一个新的变量--返回出去的内容 本质就是表对象local obj = {}--元表知识 __index 当找自己的变量 找不到时 就会去找元素中_index指向的内容self.__index = selfsetmetatable(obj, self)return obj
endlocal myObj = Object:new()
print(myObj)
print(myObj.id)
myObj:Test()
--对空表中 申明一个新的属性id,不会改变元表中的
myObj.id = 2
-- 总结一下:找的到就用自己的,找不到就用别人的,谁调用用谁的self
print(Object.id) -- 还是输出 1
myObj:Test() -- 这里会输出 2print("**********继承****************")
--C# class 类名 : 继承类
--写一个用于继承的方法
function Object:subClass(className)-- _G知识点 是总表 所有声明的全局标量 都以键值对的形式存在其中_G[className] = {}--写相关继承的规则--要用到元表local obj = _G[className]-- 子类 定义个base属性 base属性代表父类obj.base = selfself.__index = selfsetmetatable(obj, self)
endObject:subClass("Person")
--print(Person)
--print(Person.id)local p1 = Person:new()
print(p1.id) -- 还是打印的 Object 的 id 1
p1.id = 100
print(p1.id)
p1:Test()Object:subClass("Monster")
local m1 = Monster:new()
print(m1.id)
m1.id = 200
print(m1.id)
m1:Test()-- 补充 _G 的一些其他用法
--print(_G) --输出 table 加 地址 _G本质也是一张表
--_G["a"] = 1
--_G.b = "123"
--print(a) -- 1
--print(b) -- 123print("**********多态***************")
--多态:相同行为 不同表现 就是多态
-- 相同方法 不同执行逻辑 就是多态
Object:subClass("GameObject")
GameObject.posX = 0
GameObject.posY = 0
function GameObject:Move()self.posX = self.posX + 1self.posY = self.posY + 1print(self.posX)print(self.posY)
endGameObject:subClass("Player")
-- 这样就已经实现了多态的 相同方法 不同表现 但是问题来了 我们如何保留父类的逻辑
function Player:Move()--base 指定是 GameObject 表(类)--这种方式调用 相当于是把基类表 作为第一个参数传入方法中--导致它们都在共用 GameObject中的Move方法数据--self.base:Move() --通过 记录的base 来保留父类的方法逻辑--我们如果要执行父类逻辑 我们不要直接使用冒号调用--要通过 . 来调用 然后自己传入第一个参数self.base.Move(self)
endlocal p1 = Player:new()
p1:Move()
p1:Move()-- but 目前这种写法 有bug 不同对象使用的成员变量 是相同的成员变量
-- 并没有使用它们自己的
local p2 = Player:new()
p2:Move()

总结
--面向对象实现
--万物之父 所有对象的基类 Object-- 封装
Object = {}--实例化方法
function Object:new()local obj = {}--给空对象设置元表 以及 __indexself.__index = selfsetmetatable(obj, self)return obj
end--继承
function Object:subClass(className)--根据名字生成一张表 就是一个类_G[className] = {}local obj = _G[className]--设置自己的“父类”obj.base = self--给子类设置元表 以及 __indexself.__index = selfsetmetatable(obj, self)
end-- 多态 一般是在使用中的一种表现--测试
--申明一个新的类
Object:subClass("GameObject")
--成员变量
GameObject.posX = 0
GameObject.posY = 0
--成员方法
function GameObject:Move()self.posX = self.posX + 1self.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)--申明一个新的类 Player 继承 GameObject
GameObject:subClass("Player")
--多态 重写 GameObject的Move方法
function Player:Move()--base调用父类方法 用 . 自己传第一个参数self.base.Move(self)
endprint("*******")
--声明实例化 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)

16.自带库

print("************自带库*********")
--string
--table
print("************数字运算*********")
--系统时间
print(os.time())
--自己传入参数 得到时间
print(os.time({year = 2014, month = 8, day = 14}))-- os.date("*t")
local nowTime = os.date("*t")
for k,v in pairs(nowTime) doprint(k,v)
end
print(nowTime.day)
print(nowTime.hour)print("************数学运算*********")
--math
--绝对值
print(math.abs(-11))
--弧度转角度
print(math.deg(math.pi))
--三角函数 传的是弧度
print(math.cos(math.pi)) --其它的sin...都是这样--向下向上取整
print(math.floor(2.6))
print(math.ceil(5.1))--最大最小值
print(math.max(1,2))
print(math.min(4,5))--小数分离 分成整数部分和小数部分
print(math.modf(1.2)) -- 1 0.2-- 幂运算 还有^ 也是
print(math.pow(2, 5))--随机数
--先设置随机数种子
math.randomseed(os.time())
print(math.random(100))
print(math.random(100))--开方 就是开根号
print(math.sqrt(9))print("************路径*********")
--lua脚本加载路径
print(package.path)
package.path = package.path .. ";C:\\"
print(package.path)

17.Lua垃圾回收





相关文章:
热更新解决方案2 —— Lua语法相关知识点
概述 开发环境搭建 Lua语法 1.第一个Lua程序 2.变量 print("******变量*******"); --lua当中的简单变量类型 -- nil number string boolean -- lua 中所有的变量声明 都不需要声明变量类型 它会自动的判断类型 -- 类似C# 中的var --lua中的一个变量 可以随便赋值 ——…...
【c++ arx选项板】
static void xlArx_gmenu(void) {if (!g_pPaletteSetEx){g_pPaletteSetEx=CTunnelSectionPaletteSetEx::Instance(...
新时代下吉林省城乡流动人才就业问题及路径探析
摘要:新时代背景下,中国经济快速发展,城乡融合发展成为缩小城乡差距,推动共同富裕的重要方式。吉林省作为东北老工业基地,传统产业竞争优势减弱,城乡流动人才就业规模增加,并呈现“农村-城市”的…...
Go 1.19.4 命令调用、日志、包管理、反射-Day 17
1. 系统命令调用 所谓的命令调用,就是通过os,找到系统中编译好的可执行文件,然后加载到内存中,变成进程。 1.1 exec.LookPath(寻找命令) 作用: exec.LookPath 函数用于在系统的环境变量中搜索可…...
Unity 2d UI 实时跟随场景3d物体
2d UI 实时跟随场景3d物体位置,显示 3d 物体头顶信息,看起来像是场景中的3dUI,实质是2d UIusing System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using UnityEngine.UI; /// <summary>…...
全方面熟悉Maven项目管理工具(二)坐标、pom.xml文件的解读!
1. 坐标(核心概念) 1.1 数学中的坐标 使用 x、y、z 三个向量作为空间的坐标系,可以在空间中唯一的定位到一个点 1.2 Maven 中的坐标 1.2.1 向量说明: 使用三个向量在 Maven的仓库 中唯一的定位到一个 jar 包 groupId…...
php常用设计模式之单例模式
设计模式是我们日常开发中最常用的编程模式之一,也是面试中最高频的考点之一。通过合理运用设计模式,可以使代码结构更加清晰、易于维护。通过这篇文章 我也讲一下设计模式中的单例模式,了解下它的原理和适用场景。 单例模式 单例模式&…...
一文搞懂Android主题和样式
1. 概念与作用 1.1 定义与组成 Android Theme是用于定义应用程序或其部分的视觉和界面风格的一种资源。主题在Android中扮演着重要的角色,它们允许开发者统一和自定义应用的外观和感觉。一个主题定义了一组属性集合,这些属性可以是颜色、字体、控件样式…...
360与重庆科技大学战略携手,为数字中国建设输送实战人才
近日,360数字安全集团与重庆科技大学正式签订了战略合作协议,双方将围绕创新人才培养、科研技术攻关、专业实验室共建、车联网安全以及社会服务等多个维度展开深度合作,共同打造数字安全人才培养新高地,为数字重庆的建设与发展注入…...
基于异常合成的图像异常检测方法
基于异常合成的图像异常检测方法 基于异常合成思路实现图像异常检测的方法,它们的核心思路是: 试图通过合成异常样本穷尽所有可能出现的异常类型,从而将无监督的异常检测(one class classification)建模为一个全监督…...
机器学习方向在算法优化上有哪些创新点?
以下是机器学习算法优化方面的一些创新点: 一、优化算法自身的改进 随机梯度下降(SGD)的变体 Adagrad 传统的随机梯度下降算法使用固定的学习率,而Adagrad根据每个参数的历史梯度信息自适应地调整学习率。对于稀疏数据,它可以为不同的参数分配不同的学习率,使得频繁出现…...
基于yolov8的道路交通事故检测系统python源码+onnx模型+评估指标曲线+精美GUI界面
【算法介绍】 基于YOLOV8的道路交通事故检测系统是一种先进的智能交通监控解决方案,它利用YOLOV8这一前沿的目标检测算法,实现对交通事故的高效、实时检测。 该系统结合了自定义的道路交通事故数据集,对YOLOV8模型进行了针对性的训练与优化…...
HttpUtils 详解
一、详解 1.1 介绍 现如今的 Web 项目,由服务端向外发起网络请求的场景,基本上随处可见! 传统情况下,在服务端代码里访问 http 服务时,一般会使用 JDK 的 HttpURLConnection 或者 Apache 的 HttpClient,不…...
云计算第四阶段: cloud二周目 07-08
cloud 07 一、k8s服务管理 创建服务 # 资源清单文件 [rootmaster ~]# kubectl create service clusterip websvc --tcp80:80 --dry-runclient -o yaml [rootmaster ~]# vim websvc.yaml --- kind: Service apiVersion: v1 metadata:name: websvc spec:type: ClusterIPselector…...
智能合约开发工具Remix
不久前,我在B站、视频号和 YouTube 都陆续发布了新的一套免费视频课程《智能合约开发工具Remix》,总共分为了 9 个小节的视频,以下分别是这 9 个小节在 B 站的视频链接,喜欢直接看视频的伙伴可以去 B 站观看: 概况文件…...
YYF桌面 1.2 | 个性化桌面体验,清爽美观。
YYF桌面是一款经过定制的安卓桌面启动器,此版本基于1.2版本进行了一系列个性化修改。主界面快捷图标进行了美化处理,并采用了清爽半透明的图标背景。取消了底部快捷键,并重新制作了“全部应用”按钮,保留了动态效果。修改了右上角…...
【人工智能/计算机工程/大数据】第五届人工智能与计算工程国际学术会议(ICAICE 2024,2024年11月8-10日)
The 5th International Conference on Artificial Intelligence and Computer Engineering 第五届人工智能与计算工程国际学术会议(ICAICE 2024) 会议官网:www.event-icaice.org The 5th International Conference on Artificial Intellige…...
uni-app录音功能
纯纯干货,cv即用 <template><!-- 录音页面 --><view class"page"><view class"tape_box"><view class"upload_box1"><view class"upload_top"><view class"upload_img_title…...
C语言【调试】(个人笔记版)
调试 前言一、Bug二、调试工具1.DeBug2.Release 三、调试快捷键1、断点 四、调试时查看程序的当前信息1、查看临时变量2、查看内存3、查看调用堆栈、汇编、寄存器 总结 前言 这篇文章大都是我的个人笔记: 调试在日常程序设计中是很重要的。调试说白了就是为了解决代…...
连锁收银系统
商淘云连锁管理系统助力连锁企业实现“人货账”全方位数字化管理,它依托连锁品牌进销存管理实现门店订货、线下收银、线上商城、会员营销等一体化管理。 门店订货补货支持连锁直营、加盟 不同门店不同进货价、不同门店不同商品、不同门店在线或者账期支付、门店PC或…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学
一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件,其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时,价带电子受激发跃迁至导带,形成电子-空穴对,导致材料电导率显著提升。…...
