Lua进阶学习:元表

元表的介绍

在 Lua table 中我们可以访问对应的 key 来得到 value 值,但是却无法对两个 table 进行操作(比如相加)。因此 Lua 提供了元表(Metatable),允许我们改变 table 的行为,每个行为关联了对应的元方法。例如,使用元表我们可以定义 Lua 如何计算两个 table 的相加操作 a+b。当 Lua 试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫 __add 的字段,若找到,则调用对应的值。 __add 等即时字段,其对应的值(往往是一个函数或是 table)就是"元方法"


设置元表

setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
getmetatable(table): 返回对象的元表(metatable)。

-- 设置方式 1
mytable = {
    
    } -- 普通表
mymetatable = {
    
    } -- 元表
setmetatable(mytable, mymetatable) -- 把 mymetatable 设为 mytable 的元表

-- 设置方式 2
mytable2 = setmetatable({
    
    }, {
    
    })
--此时元表为匿名状态,想要获取需要使用 
print(getmetatable(mytable2)) -- > table

元方法

__tostring 和 __call 重载

__tostring 当被当做字符串使用时,调用__tostring
__call 当子表被当作一个函数使用时,调用__call

-- __tostring 和 __call
meta = {
    
    
    -- 当被当做字符串使用时,调用__tostring
    __tostring = function(t) -- 默认把自己当第一个参数传进来
        return t.str
        -- return "mmm" 
    end,
    -- 当子表被当作一个函数使用时,调用__call
    __call = function(a, b)
        print("hello", a, b) -- a 还是自己本身,b才是传的参数
    end
}
table = {
    
    str = "nnn"}
setmetatable(table, meta)
print(table) -- > 此时table被当成 string   nnn
table("123"); -- > 此时table被当成 function hello nnn 123

输出结果
在这里插入图片描述

__add等运算符重载

运算符重载 当把表进行对应的计算时可以重写运算函数

模式 描述
__add 对应的运算符 ‘+’.
__sub 对应的运算符 ‘-’.
__mul 对应的运算符 ‘*’.
__div 对应的运算符 ‘/’.
__mod 对应的运算符 ‘%’.
__unm 对应的运算符 ‘-’.
__concat 对应的运算符 ‘…’.
__eq 对应的运算符 ‘==’.
__lt 对应的运算符 ‘<’.
__le 对应的运算符 ‘<=’.

使用示例: + - ==

-- 运算符重载 当把表进行对应的计算时可以重写运算函数
meta2 = {
    
    
    __add = function(a, b)
    	 return a.age + b.age 
    end,
    __sub = function(a, b) 
    	return a.age - b.age 
    end,
    __eq = function(a, b) 
    	return a.age == b.age 
    end
}
tableA = {
    
    age = 1}
setmetatable(tableA, meta2)
tableB = {
    
    age = 3}

print(tableA + tableB) -- > 4
print(tableA - tableB) -- > -2
print(tableA == tableB) -- > true

输出结果
在这里插入图片描述

__index 和 _newindex

__index 当找不到对应属性时 找元表设置的__index所指向的表
rawget() 忽略__index

meta3 = {
    
    }
table3 = {
    
    }
table4 = {
    
    age = 3}
setmetatable(table3, meta3)

print(table3.age) -- > nil 
meta3.__index = {
    
    age = 4} -- 设置 __index
print(table3.age) -- > 4 
meta3.__index = table4 -- 设置 __index表为 table4
print(table3.age) -- > 3 
print(rawget(table3, "age")) -- > nil 

-- __index 还可以套用
meta4 = {
    
    name = "111"}
meta4.__index = meta4
setmetatable(table4, meta4)
print(table3.name) -- > 111  

输出结果
在这里插入图片描述

__newindex 当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作
rawset() 忽略__newindex

meta5 = {
    
    }
meta5.__newindex = {
    
    }
table5 = {
    
    }
setmetatable(table5, meta5)
table5.age = 1 -- 实际上这时改掉的时 元表 __newindex 里的age
print(table5.age) -- > nil 
print(meta5.__newindex.age) -- > 1 

-- 使用rawset() 就不会设置到__newindex上去了
rawset(table5, "age", 2)
print(table5.age) -- > 2
-- __newindex也是一层层往上找

输出结果
在这里插入图片描述

其他元方法

模式 描述
__idiv the floor division (//) operation. Behavior similar to the addition operation.
__band the bitwise AND (&) operation. Behavior similar to the addition operation, except that Lua will try a metamethod if any operand is neither an integer nor a float coercible to an integer (see §3.4.3)
__bor the bitwise OR (
__bxor the bitwise exclusive OR (binary ~) operation. Behavior similar to the bitwise AND operation.
__bnot the bitwise NOT (unary ~) operation. Behavior similar to the bitwise AND operation.
__shl the bitwise left shift (<<) operation. Behavior similar to the bitwise AND operation.
__shr the bitwise right shift (>>) operation. Behavior similar to the bitwise AND operation.
__len the length () operation. If the object is not a string, Lua will try its metamethod. If there is a metamethod, Lua calls it with the object as argument, and the result of the call (always adjusted to one value) is the result of the operation. If there is no metamethod but the object is a table, then Lua uses the table length operation (see §3.4.7). Otherwise, Lua raises an error. #

END

参考链接 http://www.lua.org/manual/5.4/manual.html
参考链接 https://www.runoob.com/lua/lua-metatables.html

猜你喜欢

转载自blog.csdn.net/wa36d/article/details/127380426