C#使用者的lua学习笔记——多脚本 协程 特殊用法 元表
多脚本执行
前面我们曾经谈到作用域的问题 对于lua来说如非local那么所有的都是全局
这一点在多脚本的情况下仍然是成立的 对于一个在该脚本local的变量 自然是不可以被其它脚本调用的
--加载脚本 --关键字 require("脚本名") require(‘脚本名’) require("Test") --如果是require加载执行的脚本 加载一次后不会被再执行 print(package.loaded["Test"]) --返回值是bool 意思是该脚本是否被执行 --卸载脚本 即置空 但一般不需要特意卸载 package.loaded["Test"] =nil
_G(大G表)
_G表 是一个table
将我们声明的所有全局变量都存储在其中
for k,v in pairs(_G) do print(k,v) end
加了local的变量是不会存到大G表中的
协程
概念和Unity中的基本是类似的
但lua中的协程是一个特殊的线程(本质还是线程)
这点和Unity是不同的(Unity的协程不是线程)
一个可以暂停 恢复的线程 从而使得主线程不受阻塞的运行
--协程的创建 fun = function() print(123) end co = coroutine.create(fun) --协程的本质是一个线程对象 co2 = coroutine.wrap(fun) --这里的类型不是线程 而是函数 --协程的运行 coroutine.resume(co) --对应create创建的协程 co2() --对应wrap创建的协程 --协程的挂起 fun2 = function() while true do print(123) corotine.yield() end end co3 = coroutine.create(fun2) coroutine.resume(co3) --挂起后要再次调用 否则只会执行一次 --resume有多个返回值 --第一个返回值代表协程是否启动成功 --之后是yield里面的返回值 --而通过wrap开启的协程 --会把yield的返回值直接返回出来 --协程的状态 coroutine.status(协程对象) --有三种状态 --dead 死亡 --suspended 暂停 --running 执行中 print(coroutine.status(co3)) --suspended print(coroutine.status(co)) --dead 因为没有挂起 所以判断为死亡了 --这个函数可以得到当前正在运行的协程的线程编号 coroutine.running()
特殊用法
多变量赋值
a,b,c = 1,2,"123" a,b,c = 1,2 --1 2 nil --多变量赋值 如果值不够会自动补空 a,b,c = 1,2,3,4,5,6 --多的值会忽略
多返回值
function Test() return 1,2,3,4 end --多返回值 有几个变量接就接几个 --多了补空 少了忽略 a,b,c = Test()
三目运算符的实现
知识回顾 短路现象
检测到符合条件后 逻辑运算符后的内容不会执行
只在必要时才对后面的操作进行求值 被称为“短路求值”原则
lua不支持三目运算符 但是可以通过and or做到类似的效果
x = 3 y = 2 local res = (x>y) and x or y print(res)
如果and成立了 那么or y这部分因为短路自然不会执行
反之 如果and不成立 那么就会执行y
所以就实现了三目的效果
元表
任何表变量都可以作为另一个表变量的元表
任何表变量都可以有自己的元表(父)
当我们子表中进行一些特定操作时
会执行元表中的内容
--设置元表 meta = {} myTable = {} --第一个参数 子表 第二个参数 元表 setmetatable(myTable,meta) __tostring meta2 = { __tostring = function(t) return t.name end } myTable2 = { name = "123" } setmetatable(myTable2, meta2) print(myTable2) --输出123 --当子表要被当做字符串使用时 会默认调用这个元表中的tostring方法 --相当于重写了字符串的方法 __call meta3 = { __call = function(a) print(a) print("456") end } myTable3 = { name = "123" } setmetatable(myTable3, meta3) --当子表 被当作一个函数来使用时 会默认调用这个call中的内容 myTable3() --会输出 --123 --456 --运算符重载 meta4 = { --相当于运算符重载 子表使用+运算符时会调用 __add = function(t1,t2) return t1.age + t2.age end } myTable4 = {age = 1} setmetatable(myTable4, meta4) myTable5 = {age = 2} print(myTable4 + myTable5) --其它可重载的 __sub减 __mul乘 __div除 __mod取余 __pow幂运算 __eq == __lt < __le <= --重载了小于就相当于重载了大于 __concat 拼接 --如果要用条件运算符 来比较两个对象 --这两个对象的元表一定要一致 才能准确调用方法 --__index 和_ _newindex meta6 = { age = 1 } meta6.__index = meta6 --也可以把赋值写到外面meta6.__index = {age = 2} --但是__index的赋值得写在表外面 myTable6 = {} setmetatable(myTable6, meta6) print(myTable6.age) --__index 当子表中 找不到某一个属性时 --会到元表中 __index指定的表去找索引 --__index可以一层一层嵌套 --__newindex 当赋值时 如果赋值一个不存在的索引 --那么会把这个值赋值到newindex所指的表中 不会修改自己 meta7 = {} meta7.__newindex = {} myTable7 = {} setmetatable(myTable7,meta7) myTable7.age = 1 print(myTable7.age) 输出nil print(neta7.__newIndex.age) 输出7 --其它 --得到元表的方法 getmetatable(myTable) --找自己身上有没有这个变量 不考虑元表 如果没有就返回nil rawget(myTable, "age") --绕开__newindex 只会改自己的变量 rawset(myTable, "age", 2)