原文地址为:
Lua:元表(metatable)与元方法(meatmethod)
转载请注明本文地址: Lua:元表(metatable)与元方法(meatmethod)
元表概念:
元表实例
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》元表与元方法整张的实例
--[[
Set = {}
mt = {} --元表
function Set.new(l)
local set = {}
setmetatable(set, mt)
for _, v in ipairs(l) do
set[v] = true
end
return set
end
--================================================
function Set.tostring(set)
local l = {}
for e in 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 k in pairs(a) do res[k] = true end
for k in 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 k in 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 k in 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"
转载请注明本文地址: Lua:元表(metatable)与元方法(meatmethod)