-
元表概念:
-
引言:Lua中的每个值都有一套预定义的操作集合,如数字相加等。但无法将两个table相加,此时可通过元表修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定操作。
-
访问机制:一般的元方法都只针对Lua的核心,也就是一个虚拟机。它会检测一个操作中的值是否有元表,这些元表是否定义了关于次操作的元方法。例如两个table相加,先检查两者之一是否有元表,之后检查是否有一个叫“__add”的字段,若找到,则调用对应的值。“__add”等即时字段,其对应的值(往往是一个函数或是table)就是“元方法”。
-
-
元表实例
-
setmetatable(只能用于table)和getmetatable(用于任何对象)
-
语法:setmetatable (table, metatable),对指定table设置metatable 【如果元表(metatable)中存在__metatable键值,setmetatable会失败】
-
语法:tmeta = getmetatable (tab),返回对象的元表(metatable) 【如果元表(metatable)中存在__metatable键值,当返回__metatable的值】
-
代码:
print(getmetatable("lua")) -->table: 002F19B8 print(getmetatable(10)) -->nil --使用__metatable可以保护元表,禁止用户访问元表中的成员或者修改元表。 tA = {} mt = {} getmetatable(tA, mt) mt.__metatable = "lock" setmetatable(tA, mt) print(getmetatable(tA)) -->lock
-
- 算术类元方法: 字段:__add __mul __ sub __div __unm __mod __pow (__concat)
- 代码:(两个table相加)
tA = {1, 3} tB = {5, 7} --tSum = tA + tB mt = {} mt.__add = function(t1, t2) for _, item in ipairs(t2)do table.insert(t1, item) end return t1 end setmetatable(tA, mt) tSum = tA + tB for k, v in pairs(tSum)do print(v) end
- 代码:(两个table相加)
- 关系类元方法: 字段:__eq __lt(<) __le(<=),其他Lua自动转换 a~=b --> not(a == b) a > b --> b < a a >= b --> b <= a 【注意NaN的情况】
- 代码:
--比较集合大小 < mt = {} function mt.__lt(tA, tB) return #tA < #tB end tA, tB = {3}, {1, 2} setmetatable(tA, mt) setmetatable(tB, mt) print(tA < tB)
- 代码:
-
table访问的元方法: 字段: __index __newindex
-
__index:
查询:访问表中不存的字段
rawget(t, i) -
__newindex:
更新:向表中不存在索引赋值
rawswt(t, k, v)
-
-
-
贯穿《Programming in Lua》元表与元方法整张的实例
<span style="font-family: 黑体;">--[[ Set = {} mt = {} --元表 function Set.new(l) localset = {} setmetatable(set, mt) for _, v in ipairs(l)do set[v] = true end return set end --================================================ function Set.tostring(set) local l = {} for ein pairs(set)do l[#l + 1] = e end return "{" .. table.concat(l, ",") .. "}" end function Set.print(s) print(Set.tostring(s)) end --1 加(__add), 并集=============================== function Set.union(a, b) --[[ if getmetatable(a) ~= mt or getmetatable(b) ~= mt then error("attemp to 'add' a set with a non-set value", 2) --error第二个参数的含义P116 end]] local res = Set.new{} for kin pairs(a)do res[k] = true end for kin pairs(b)do res[k] = true end return res end s1 = Set.new{10, 20, 30, 50} s2 = Set.new{30, 1} --print(getmetatable(s1)) --print(getmetatable(s2)) mt.__add = Set.union s3 = s1 + s2 --Set.print(s3) --[[元表混用 s = Set.new{1, 2, 3} s = s + 8 Set.print(s + 8) ]] --2 乘(__mul), 交集============================== function Set.intersection(a, b) local res = Set.new{} for kin pairs(a)do res[k] = b[k] end return res end mt.__mul = Set.intersection --Set.print(s2 * s1) --3 关系类===================================NaN的概念==== mt.__le = function(a, b) for kin pairs(a)do if not b[k] then return false end end return true end mt.__lt = function(a, b) return a <= b and not (b <= a) end mt.__eq = function(a, b) --竟然能这么用!?---- return a <= b and b <= a end g1 = Set.new{2, 4, 3} g2 = Set.new{4, 10, 2} print(g1 <= g2) print(g1 < g2) print(g1 >= g2) print(g1 > g2) print(g1 == g1 * g2) --]] --============================================ --4 table访问的元方法========================= --[[ --__index有关继承的典型示例 Window = {} Window.prototype = {x = 0, y = 0, width = 100, height} Window.mt = {} 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) --__index修改table默认值 function setDefault (t, d) local mt = {__index = function () return d end} setmetatable(t, mt) end tab = {x = 10, y = 20} print(tab.x, tab.z) setDefault(tab, 0) print(tab.x, tab.z) --]] --13.4.5 只读的table function readOnly(t) local proxy = {} local mt = { __index = t, __newindex = function(t, k, v) error("attempt to update a read-only table", 2) end } setmetatable(proxy, mt) return proxy end days = readOnly{"Sunday","Monday","Tuesday","W","T","F","S"} print(days[1]) days[2] = "Noday"</span>
Lua:元表(metatable)与元方法(meatmethod)
最新推荐文章于 2024-03-17 12:16:44 发布