Lua元表(Metatable)详解

作者:陈劲灿 编辑日期: 2017年3月31日 16:14 阅读量: 376 分类: program
Lua元表简介
两个重要的函数
1.
2.
3.
t = {}
print(getmetatable(t))
--> nil
1.
2.
3.
t1 = {}
setmetatable(t, t1)
assert(getmetatable(t) == t1)
表所拥有的元方法
算 术 运 算 的 M e t a m e t h o d s
元方法 含义
__add
__sub
__mul
__div
__mod 取模
__unm
__concat 连接(..)
关 系 运 算 的 M e t a m e t h o d s
元方法 含义
__eq 等于
__lt 小于
__le 小于等于

注意:对剩下的三个关系运算符没有专门的 metamethod, 因为 Lua 将 a ~= b 转换为 not (a == b);a > b 转换为 b < a;a >= b 转换为 b <= a。

库 定 义 的 M e t a m e t h o d s
元方法 含义
__tostring tostring优先检查的域
__metatable setmetatable/getmetatable 函 数 也 会 使 用 metafield 可 以 保 护metatables
表 相 关 的 M e t a m e t h o d s
元方法 含义
__index 当我们访问一个表的不存在的域,触发 lua 解释器去查找index metamethod:如果不存在,返回结果为 nil;如果存在则由index metamethod 返回结果
__newindex newindex metamethod 用来对表更新,index 则用来对表访问。当你给表的一个缺少的域赋值,解释器就会查找__newindex metamethod:如果存在则调用这个函数而不进行赋值操作
元表的应用
 1.
 2.
 3.
 4.
 5.
 6.
 7.
 8.
 9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
Set = {}
Set.mt = {}

function Set.new(t)
    local set = {}
    setmetatable(set, Set.mt)
    for _, l in ipairs(t) do set[l] = true end
    return set
end

function Set.union(a, b)
    local res = Set.new{}
    for k in pairs(a) do res[k] = true end
    for k in pairs(b) do res[k] = true end
    return res
end

function Set.intersection(a, b)
    local res = Set.new{}
    for k in pairs(a) do
        res[k] = b[k]
    end
    return res
end

function Set.tostring(set)
    local s = "{"
    local sep = ""
    for e in pairs(set) do
        s = s .. sep .. e
        sep = ","
    end
    return s .. "}"
end

function Set.print(s)
    print(Set.tostring(s))
end

Set.mt.__add = Set.union
Set.mt.__mul = Set.intersection
Set.mt.__tostring = Set.tostring
Set.mt.__le = function(a, b)
    for k in pairs(a) do
        if not b[k] then return false end
    end
    return true
end
Set.mt.__lt = function(a, b)
    return a <= b and not (b <= a)
end
Set.mt.__metatable = "Not Your business!"

s1 = Set.new{10, 20, 30, 50}
s2 = Set.new{30, 1}
print(getmetatable(s1))
print(getmetatable(s2))

s3 = s1 + s2
Set.print(s3)
--> {1, 10, 20, 30, 50}

Set.mt.__mul = Set.intersection
Set.print((s1 + s2)*s1)
--> {10, 20, 30, 50}

s1 = Set.new{2, 4}
s2 = Set.new{4, 10, 2}
print(s1 <= s2) --> true
print(s1 < s2) --> true
print(s1 >= s1) --> true
print(s1 > s1) --> false
print(s1 == s2 * s1) --> true

s1 = Set.new{10, 4, 5}
print(s1)
--> {4, 5, 10}

Set.mt.__metatable = "not your business"
s1 = Set.new{}
print(getmetatable(s1))
--> not your business
setmetatable(s1, {})
--stdin1: cannot change protected metatable

index and newIndex

 1.
 2.
 3.
 4.
 5.
 6.
 7.
 8.
 9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
-- create a namespace
Window = {}
-- create the prototype with default values
Window.prototype = {x=0, y=0, width=100, height=100, }
-- create a metatable
Window.mt = {}
-- declare the constructor function
function Window.new (o)
setmetatable(o, Window.mt)
return o
end

Window.mt.__index = function (table, key)
return Window.prototype[key]
end

w = Window.new{x=10, y=20}
print(w.width)
--> 100

Window.mt.__index = Window.prototype
Window.prototype["width"]

Lua的元表可以给表添加很多元方法,通过表元方法index可以获取元表的值,可以理解为继承了元表。通过newindex设置不能进行表更新,从而让表变为只读表.


上一篇
下一篇
栈的应用之判断符号是否对称
一行Python代码实现简单HTTP服务器