鸟语天空
Lua元表(Metatable)
post by:追风剑情 2022-4-19 15:11

有两个很重要的函数来处理元表:
setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
getmetatable(table): 返回对象的元表(metatable)。

给table设置元表
mytable = {}
mymetatable = {}
setmetatable(mytable, mymetatable)
-- 或者写成一行
-- setmetatable({}, {})

-- 返回mymetatable
getmetatable(mytable)

__index 元方法

这是 metatable 最常用的键。当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。

实例
other = { foo=3 }
t = setmetatable({}, { __index = other })
print(t.foo)

如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。__index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。

实例
mytable = setmetatable({key1 = "value1"}, {
	__index = function(mytable, key)
		if key == "key2" then
			return "metatablevalue"
		else
			return nil
		end
	end
})

提示   利用元表(metatable)和__index元方法可实现继承

__newindex 元方法

为一个不存在的键赋值时,解释器会检查__newindex元方法是否为table,如果是则在__newindex上创建新键并赋值。

实例
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1)

-- 将在mymetable中创建newkey并赋值为"新值2"
mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)

mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)

如果__newindex为函数。

实例
mytable = setmetatable({key1 = "value1"}, {
    __newindex = function(mytable, key, value)
        rawset(mytable, key, "\""..value.."\"")
    end
})

mytable.key1 = "new value"
-- 解释器会调用__newindex函数
mytable.key2 = 4

print(mytable.key1,mytable.key2)

为表添加操作符

实例
-- 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用
-- 自定义计算表中最大键值函数 table_maxn,即计算表的元素个数
function table_maxn(t)
    local mn = 0
    for k, v in pairs(t) do
        if mn < k then
            mn = k
        end
    end
    return mn
end

-- 两表相加操作
mytable = setmetatable({ 1, 2, 3 }, {
  __add = function(mytable, newtable)
    for i = 1, table_maxn(newtable) do
      table.insert(mytable, table_maxn(mytable)+1,newtable[i])
    end
    return mytable
  end
})

secondtable = {4,5,6}

-- 解释器会调用元表中的__add元方法
mytable = mytable + secondtable

for k,v in ipairs(mytable) do
	print(k,v)
end

操作符元方法列表
模式 描述
__add 对应的运算符 '+'
__sub 对应的运算符 '-'
__mul 对应的运算符 '*'
__div 对应的运算符 '/'
__mod 对应的运算符 '%'
__unm 对应的运算符 '-'(负号)
__concat 对应的运算符 '..'
__eq 对应的运算符 '=='
__lt 对应的运算符 '<'
__le 对应的运算符 '<='

__call 元方法

实例
-- 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用
-- 自定义计算表中最大键值函数 table_maxn,即计算表的元素个数
function table_maxn(t)
    local mn = 0
    for k, v in pairs(t) do
        if mn < k then
            mn = k
        end
    end
    return mn
end

-- 定义元方法__call
mytable = setmetatable({10}, {
  __call = function(mytable, newtable)
        sum = 0
        for i = 1, table_maxn(mytable) do
                sum = sum + mytable[i]
        end
    for i = 1, table_maxn(newtable) do
                sum = sum + newtable[i]
        end
        return sum
  end
})
newtable = {10,20,30}
print(mytable(newtable)) -- 输出70

__tostring 元方法

__tostring 元方法用于修改表的输出行为。以下实例我们自定义了表的输出内容:

实例
mytable = setmetatable({ 10, 20, 30 }, {
  __tostring = function(mytable)
    sum = 0
    for k, v in pairs(mytable) do
                sum = sum + v
        end
    return "表所有元素的和为 " .. sum
  end
})
-- 输出: 表所有元素的和为 60
print(mytable)

评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容