lua学习笔记11-----表相关的metatable and metamathods

之前提过metatable中的metamathdos触发的条件可以是由lua系统规定(table运算时触发)的,也可以由一些库文件(tostring)指定。
实际上metamathdos的触发,也可以由其他方式达到。
比如说,访问table不存在的域的时候,会查找table的metatable中的__index metamathdos
更新table不存在的域的时候,会查找table的metatable中的__newindex metamathdos
下面来具体介绍以下这两个metamathdos是如何工作的。

访问一个table不存在的域的时候,会查找这个table的metatable中的__index metamathdos。
如果不存在,那么访问的结果就是 nil;
如果存在,返回的结果将由__index给出。
我们来举一个简单的例子:
假设需要一个窗口的table,在创建这个窗口table的时候,希望它能够带有 横坐标,纵坐标,高度,宽度 四个属性的默认值。
目前我们有两种方法。
第一种,就是通过构造器函数,在创建窗口table之后,向它添加这四种属性并添加默认值。
第二种,通过窗口table的metatable的__index域实现。
代码如下:

Set = {}
Set.mt = {}
Set.prototype = {x = 0,y = 0,weight = 100,height = 50}
function DefaultNum(set,v)
        local mt={__index = function () return v end}
        setmetatable(set,mt)
end
function Set.New(set)
        local s = set
        setmetatable(s,Set.mt)
        return set
end
function Set.index(set,key)
        return Set.prototype[key]
end
do
        Set.mt.__index = Set.index
        local w = Set.New{}
        print(w.weight)
end

通过构造器创建了一个空的table,这个table的metatable是Set.mt。
当对w中的weight域进行访问的时候(print(w.weight)),由于w并没有这个域,所以lua去w的metatable中寻找__index metamathdos 。
lua会把table名称和索引值传给__index处理,最后按照__index的返回值来打印。

对table进行更新的时候(通过 table[key] = value 的方式为表增加一个域)。
如果table的metatable中包含__newindex metamathdos,lua会把table名,key,value传给__newindex,由它来处理这次对table的更新。
如果__newindex是一张表,那就会直接更新给这张表。上述两种情况下,lua都不会对table进行更新(不过可以通过__newindex对table更新)。
以下代码对__newindex的特点进行了应用

Set = {}
Set.mt = {}
function Set.New(set)
        local s = set
        setmetatable(s,Set.mt)
        return set
end
function Set.newindex(t,k,v)
        Set[k] = v
end
function Set.tostring(t)
        local set = "{"
        local qes = ""
        for k in pairs(t) do
                set = set..qes..k
                qes = ", "
        end
        set = set.."}"
        return set
end
do
        Set.mt.__newindex = Set.newindex
        Set.mt.__tostring = Set.tostring
        local w = Set.New{}
        print(w)
        w.z = 10
        print(w)
        print(Set.z)
        Set.mt.__newindex = {}
        w.p = 20
        print(w)
        print(Set.mt.__newindex.p)
end

你可能感兴趣的:(lua)