-
元表概念:
-
引言:Lua中的每个值都有一套预定义的操作集合,如数字相加等。但无法将两个table相加,此时可通过元表修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定操作。
-
访问机制:一般的元方法都只针对Lua的核心,也就是一个虚拟机。它会检测一个操作中的值是否有元表,这些元表是否定义了关于次操作的元方法。例如两个table相加,先检查两者之一是否有元表,之后检查是否有一个叫“__add”的字段,若找到,则调用对应的值。“__add”等即时字段,其对应的值(往往是一个函数或是table)就是“元方法”。
-
元表实例
-
贯穿《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"
-
|
请发表评论