Lua语言中的__index,__newindex,rawget和rawset

转自:http://blog.csdn.net/wangbin_jxust/article/details/12108189

在谈及Lua中的__index,__newindex,rawget和rawset前,需要理解Lua中的元表这个概念。

零、元表的概念

对Lua中元表的解释: 元表可以改变表的行为模式。

这里举个例子:

Window = {}  

Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,}  

Window.mt = {}  

function Window.new(o)
    setmetatable(o ,Window.mt)
    return o
end  

Window.mt.__index = Window.prototype  

Window.mt.__newindex = function (table ,key ,value)
    if key == "wangbin" then
        rawset(table ,"wangbin" ,"yes,i am")
    end
end  

w = 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 o
end
Window.mt.__index = function (t ,key)
    -- body
    return 1000
end
w = Window.new{x = 10 ,y = 20}
print(w.wangbin)  

打印结果是:1000。这里可以看出,我们在new的时候,w这个表里其实没有wangbin这个元素的,我们重写了元表中的__index,使其返回1000,意思是:如果你要寻找的元素,该表中没有,那么默认返回1000。

备注:__index也可以是一个表,我们这里也可以写__index = {wangbin = 1000},打印的值仍然可以是1000。

二、__newindex的理解

__newindex:当给你的表中不存在的值进行赋值时,lua解释器则会寻找__newindex元方法,发现存在该方法,则执行该方法进行赋值,注意,是使用rawset来进行赋值,至于原因,后面会讲到。

Window.mt = {}
function Window.new(o)
    setmetatable(o ,Window.mt)
    return o
end
Window.mt.__index = function (t ,key)
    return 1000
end
Window.mt.__newindex = function (table ,key ,value)
    if key == "wangbin" then
        rawset(table ,"wangbin" ,"yes,i am")
    end
end
w = 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 o
end
Window.mt.__index = function (t ,key)
    return 1000
end
Window.mt.__newindex = function (table ,key ,value)
    if key == "wangbin" then
        rawset(table ,"wangbin" ,"yes,i am")
    end
end
w = 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 o
end
Window.mt.__index = function (t ,key)
    return 1000
end
Window.mt.__newindex = function (table ,key ,value)
    table.key = "yes,i am"
end
w = Window.new{x = 10 ,y = 20}
w.wangbin = "55"  

然后我们的程序就stack overflow了。可见,程序陷入了死循环。因为w.wangbin这个元素本来就不存在表中,然后这里不断执行进入__newindex,陷入了死循环。

时间: 2024-08-28 20:57:30

Lua语言中的__index,__newindex,rawget和rawset的相关文章

跟我一起了解Lua语言中的_index,newindex,rawget和rawset

前言:理解Lua语言中的__index, __newindex, rawget和 rawset 在谈及Lua中的__index, __newindex, rawget和rawset前,需要理解Lua中的元表这个概念. 一.元表的概念 对Lua中元表的解释: 元表可以改变表的行为模式. 这里举个例子: Window = {} Window.prototype = { x = 0 , y = 0 , width = 100 , height = 100, } Window.mt = {} funct

lua语言中闭包的学习心得

lua语言有如下两个特点: 1.lua中的函数可以被存放在变量.表中,也可以作为函数的参数,还可以作为函数的返回值,如: func = function() print("Hello"); end 等价于 function func() print("Hello"); end 这两种写法都是函数func()的定义:并且下面这个例子: function func() return function() print("Hello"); end --函

对lua继承中self.__index = self的释疑

首先看看从lua表中查找一个键时的流程: -- 当从表t中查找键k时,lua处理如下: -- 1.t中是否有k,有则直接返回值,否则第2步 -- 2.t是否有元表, 无则返回nil, 有则第3步 -- 3.t的元表是否有__index元方法, 无则返回nil, 有则查找__index指向的表或对应的方法 ---注意两种写法 -- 写法1, 可以保持继承链 local class = {} function class:new() self.__index = self return setmet

lua语言--table的构建

table是lua语言中最为重要,也是最为强大的武器,最简单的构造函数是{}.--所以说当你看到{}的时候,实际上是调用了一个构造函数. 直接初始化数组: days = {"Monday","Tuesday","Wednesday"} 初始化一个表作为record: days = {m = "Monday",t = "Tuesday",w="Wednesday"}//注意record其实

Lua脚本编程:Lua语言入门

Lua是一门简单而强大的语言,其本身强大的扩展性使得这门语言在游戏设计等领域发挥着重要的作用.博主曾在Unity3D中使用过这门语言,并且针对Lua和Unity.C++等方面的内容进行了学习和讨论.最近因为在[游戏脚本高级编程]这本书中详细介绍了Lua脚本的相关内容,因此在这里记录下博主的读书心得,方便以后在需要的时候查阅. Lua系统构成 Lua系统由Lua链接库.Luac编译器.Lua解释器三部分构成. * Lua链接库主要由lua.lib和lua.h这两个文件组成.Lua链接库主要负责对自

Lua语言基础汇总(9)-- Lua中__index和__newindex实践

前言 本文将通过几个简单的实例演示,巩固对__index和__newindex的理解,同时加深对Lua中元表和元方法的理解,如果对Lua的元表和元方法还不是很熟悉的话,请参考这篇文章:<Lua中的元表与元方法>. 具有默认值的table 我们都知道,table中的任何字段的默认值都是nil,但是通过元表,我们可以很容易的修改这一规定,代码如下: 1 2 3 4 5 6 7 8 9 function setDefault(tb, defaultValue)      local mt = {__

Lua语言基础汇总(8) -- Lua中的元表与元方法

前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理,两个table类型的变量,你是无法直接进行“+”操作的,如果你定义了一个指定的函数,就可以进行了.那本文就是主要讲的是如何定义这个指定的函数,这个指定的函数是什么?希望对学习Lua的朋友有帮助. Lua是怎么做的? 通常,Lua中的每个值都有一套预定义的操作集合,比如数字是可以相加的,字符串是可以连接

Lua语言基础汇总(10) -- Lua中的环境概念

前言 Lua将其所有的全局变量保存在一个常规的table中,这个table称为“环境”.这种组织结构的优点在于,其一,不需要再为全局变量创造一种新的数据结构,因此简化了Lua的内部实现:另一个优点是,可以像其他table一样操作这个table.为了便于实施这种操作,Lua将环境table自身保存在一个全局变量_G中.例如,我们可以使用以下代码打印当前环境中所有全局变量的名称. 1 for n in pairs(_G) do print(n) end 在你的电脑上运行一下以上代码,看看结果. 全局

Lua语言基础汇总(12)-- Lua中的面向对象编程

简单说说Lua中的面向对象 Lua中的table就是一种对象,看以下一段简单的代码: 1 2 3 4 5 6 7 8 9 10 11 12 local tb1 = {a = 1, b = 2} local tb2 = {a = 1, b = 2} local tb3 = tb1   if tb1 == tb2 then      print("tb1 == tb2") else      print("tb1 ~= tb2") end   tb3.a = 3 pri