lua防止访问不存在的全局变量
来源:互联网 发布:混沌战域仙魂进阶数据 编辑:程序博客网 时间:2024/05/21 07:47
当访问lua中不存在的全局变量时并不会报错,而是返回nil值。在我们开发的时候稍微不注意写错了变量名,程序并不会报错,类似于下面这种情况。
test = 1
print(tets)
为了防止这种情况,我们可以通过设置全局表_G的元方法__index和__newindex来解决。
全局表_G,所有的全局变量和全局函数都放在这里面,比如上面的test=1,其实是_G.test = 1。
在这之前,我们先理解lua中的__index,__newindex,rawget,rawset方法。
网上很多讲解这几个方法的,我是从这里直接拷贝过来的。
链接:http://www.myexception.cn/mobile/1439151.html
元表的概念
对Lua中元表的解释: 元表可以改变表的行为模式。
这里举个例子:
Window = {}Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,}Window.mt = {}function Window.new(o)setmetatable(o ,Window.mt)return oendWindow.mt.__index = Window.prototypeWindow.mt.__newindex = function (table ,key ,value)if key == "wangbin" thenrawset(table ,"wangbin" ,"yes,i am")endendw = Window.new{x = 10 ,y = 20}w.wangbin = "55"print(w.wangbin)
然后,我们可以看到打印信息是:yes,i am
原本赋值的地方是w.wangbin = "55",但是结果却是 yes,i am。
这里就改变了元表的行为模式。
一、__index的理解
__index是:当我们访问一个表中的元素不存在时,则会触发去寻找__index元方法,如果不存在,则返回nil,如果存在,则返回结果。
Window = {}Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,}Window.mt = {}function Window.new(o)setmetatable(o ,Window.mt)return oendWindow.mt.__index = function (t ,key)-- bodyreturn 1000endw = Window.new{x = 10 ,y = 20}print(w.wangbin)打印结果是:1000。这里可以看出,我们在new的时候,w这个表里其实没有wangbin这个元素的,我们重写了元表中的__index,使其返回1000,意思是:如果你要寻找的元素,该表中没有,那么默认返回1000。
二、__newindex的理解
__newindex:当给你的表中不存在的值进行赋值时,lua解释器则会寻找__newindex元方法,发现存在该方法,则执行该方法进行赋值,注意,是使用rawset来进行赋值,至于原因,后面会讲到。
Window.mt = {}function Window.new(o)setmetatable(o ,Window.mt)return oendWindow.mt.__index = function (t ,key)return 1000endWindow.mt.__newindex = function (table ,key ,value)if key == "wangbin" thenrawset(table ,"wangbin" ,"yes,i am")endendw = Window.new{x = 10 ,y = 20}w.wangbin = "55"print(w.wangbin)ok,这里的打印结果是:yes,i am。w这个表里本来没有wangbin这个元素的,我们重写了元表中__newindex,并在__newindex方法中重新进行赋值操作,然后,我们对这个本不存在的原色w.wangbin进行赋值时,执行__newindex方法的赋值操作,最后,打印结果便是:yes,i am
三、rawget和rawset的理解
rawget是为了绕过__index而出现的,直接点,就是让__index方法的重写无效。(我这里用到"重写"二字,可能不太对,希望能得到纠正)
Window = {}Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,}Window.mt = {}function Window.new(o)setmetatable(o ,Window.mt)return oendWindow.mt.__index = function (t ,key)return 1000endWindow.mt.__newindex = function (table ,key ,value)if key == "wangbin" thenrawset(table ,"wangbin" ,"yes,i am")endendw = Window.new{x = 10 ,y = 20}print(rawget(w ,w.wangbin))打印结果是:nil。这里的元表中__index函数就不再起作用了。
但是rawset呢,起什么作用呢?我们再来运行一段代码。
Window = {}Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,}Window.mt = {}function Window.new(o)setmetatable(o ,Window.mt)return oendWindow.mt.__index = function (t ,key)return 1000endWindow.mt.__newindex = function (table ,key ,value)table.key = "yes,i am"endw = Window.new{x = 10 ,y = 20}w.wangbin = "55"然后我们的程序就stack overflow了。可见,程序陷入了死循环。因为w.wangbin这个元素本来就不存在表中,然后这里不断执行进入__newindex,陷入了死循环。
知道了上面那些概念,我们的程序就好写了,只要重写_G的__index和__newindex方法就可以,代码如下:
local tbDefineValue = {}setmetatable(_G, {__newindex = function(tb, key, value)tbDefineValue[key] = truerawset(tb, key, value)end,__index = function(tb, key)if not tbDefineValue[key] thenerror(string.format("找不到全局变量:%s", key))return nilendend})function getValue(key, default)local flag, value = pcall(function() return _G[key] end)if flag thenreturn valueelsereturn defaultendenda = getValue('a', 111)print(a)
通过公共接口getValue来定义全局变量a,其中第二个参数为默认值。
如果访问没有定义的全局变量则会报:找不到全局变量的错误,这样就可以定位到具体哪里写错了。
- lua防止访问不存在的全局变量
- Lua Module对全局变量访问
- Lua Module对全局变量访问
- Lua Module对全局变量访问
- 10.c++给lua传递变量和访问Lua的全局变量
- Lua 全局变量
- lua全局变量
- Lua 全局变量
- c取Lua的全局变量数组
- c取Lua的全局变量数组
- Lua 的upvalues的访问
- 防止全局变量重复定义
- autohotkey关于函数访问全局变量的解决方案
- c++在类的内部访问全局变量
- 解决多线程访问全局变量的解决方案
- 防止全局变量、头文件重复包含与 extern 的使用
- lua 全局变量 2
- LUA中的全局变量环境
- 前端学习_Series2_01.JavaScript_03
- Java通过WebSocket WebRTC实现视频通话实例
- Android APK安装后点击[打开]与[完成]的区别
- 学习路上的鸡汤
- Mac下清空DNS缓存
- lua防止访问不存在的全局变量
- Sorting methods summary (1)
- OMNeT++工具的简单介绍
- 遇到问题为何该自己动手
- 图的割点、桥和双连通分支的基本概念
- 4.6.第十一个实验--使用数码管显示矩阵按键的键值
- linux中的wget命令
- 暴雪hash
- 浅拷贝和深拷贝