Lua 中元表及元表方法学习

今天花了一些时间学习了Lua元表与元表方法,这里做个笔记,方便下次理解查看

 

引言:Lua中的每个值都有一套预定义的操作集合,如数字相加等。但无法将两个table相加,此时可通过元表修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定操作。
表和完整的用户数据具有独立的元表(尽管多个表和用户数据可共享元表);每种其他类型的所有值共享一个元表。所以,所有数字共享一个元表,字符串也是,等等。

 

元表的作用:通常可以使用元表来修改一个值的行为, 使其在面对一个非预定的操作时执行一个指定的操作。
元表可以控制对象的数学运算、顺序比较、连接、取长、和索引操作的行为。元表也能定义用户数据被垃圾收集时调用的函数。Lua给这些操作的每一个都关联了称为事件的特定键。当Lua对某值执行其中一个操作时,检查该值是否含有元表以及相应的事件。如果有,与该键关联的值(元方法)控制Lua如何完成操作。

 

获取元表和设置元表的方法
 可通过函数getmetatable查询任何值的元表。
 可通过函数setmetatable替换表的元表。不能从Lua中改变其他类型的元表(除了使用调试库);必须使用C API才能做到。

 

lua查找一个元素时的规则
1 在表中查找,如果找到,返回该元素,结束查找, 反之继续
2 判断该表是否有元表, 如果没有元表则直接返回nil, 反之继续
3 判断元表有没有__index有没有元表方法,如果__index方法为空,则返回nil, 如果__index为一个函数,则返回该函数的返回值, 如果__index是一个表,则重复1、2、3步骤

 

例子:
local A = {
 a = 100
}

 

local B = {
 b = 50
}

 

setmetatable(B, A)
print(B.a)

 

运行结果: [LUA-print]: nil
分析: 此时查找时步骤1未找到。执行步骤二,存在元表, 继续执行步骤三, 此时__index方法为空, 所有直接返回为nil

 

修改:
local A = {
 a = 100
}

 

local B = {
 b = 50
}

 

A.__index = A;
setmetatable(B, A)
print(B.a)
运行结果:[LUA-print]: 100

 

元方法:
我们称元表中的键为事件(event), 称值为元方法(metamethod). 上面的例子中的index就是一个元方法
每个操作的键是由其名字前缀两个下划线“__”的字符串;例如,操作“加(add)”的键是字符串"__add"。这些操作的语义通过一个Lua函数描述解释器如何执行操作作了更好的说明。
Lua中支持的元方法
metatable通过其包含的函数来给所挂接的table定义一些特殊的操作,包括:
算数类元方法:
__add: 定义所挂接table的加法操作
__mul: 定义乘法操作
__div: 定义除法操作
__sub: 定义减法操作
__mod: 定义取模操作
__pow:定义乘幂操作
__concat: 定义连接操作(".."运算符)
关系类元方法:
__eq: 定义等于操作
__lt: 定义小于操作
__le: 定义小于等于操作

 

__len: 定义取长度操作 即# 操作
__unm: 定义一元-操作, 即: -table的含义
__tostring: 定义当table作为tostring()函式之参数被呼叫时的行为(例如: print(table)时将呼叫tostring(table)作为输出结果)
__index: 定义当table中不存在的key值被试图获取时的行为
__newindex: 定义在table中产生新key值时的行为

 

创建只读的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

 

local weekdays = readOnly{"Mon", "Tue", "Wed", "Thu", "Fri", "sat", "sun"};
print(weekdays[3]);
weekdays[1] = "Monday"

运行结果:
[LUA-print]: Wed
test.lua:(19): attempt to update a read-only table
Stack Traceback:
 [C]: in function 'error'
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值