lua中的元表和元方法解析

1.lua中的元表和元方法

lua中的每种类型都预定义了一些操作,比如数字可以相加,字符串可以拼接,表可以索引等,但是还有很多操作对于特定类型是没有预定义的,比如我们没法对两个table进行相加,元表和元方法正是提供给我们自己去丰富某些特定类型的操作的(相当于c++或者c#等等中的运算符重载一样),当然还有其他作用,比如用到面向对象里面等等。
首先,我们要知道lua中的类型除了table和userdata可有有自己独立的元表,其他的类型都是共享一个元表的,创建一个table的时候默认不会指定其元表,我们通过getmetatable()方法来获取一个table的元表,通过setmetatable()来设置一个table的元表,可以把一个table本身设置成自己的元表,也可以把一个table设置成几个行为相似的一组table的元表(经常用在面向对象中),下面看几个例子:
tab ={}
metatab ={}
print("获取tab的元表" )
print(getmetatable(tab))
print("metatab的地址"..tostring(metatab))
setmetatable(tab,metatab)
print("再次获取tab元表" .. tostring(getmetatable(tab)))


从结果可以知道上述结论是正确的,lua中只能设置table的元表,其他的类型的元表是在c中设置的(编写库的时候),系统标准的字符串库为所有字符串设置了元表,其他类型没有预设置的元表,大家可以自己打印出来看一下。
lua中的元方法就是元表中的字段对应的一个函数或者一个table,比如我有两个表,表A和表B,他们有共同的元表C,我们通过代码来演示怎么操作:
A={1,2,3,"f"}
B={4,5,6,"s"}
C={}
C.__add = function(a,b) return #a+#b end
setmetatable(A,C)
setmetatable(B,C)
print(A+B)
设置元表就不说了,先看下C的字段__add是什么意思,这其实是算术元方法的默认字段,表示算术的+,当第一个表有元表时,使用+运算符时会从其元表中去查找看有没有__add字段,如果有使用该字段定义的方法进行操作,与第二个表无关,如果第一个没有元表或者元表中没有__add字段时,会对第二个表进行同样的判断,与第一个表无关,所以前面其实我们只要设置一个表的元表为C就可以了,倘若两个都找不到,则会引发错误。算术元方法中海油很多类似的字段名,比如__mul表示乘,__sub表示减等等,这里就不一一列出了,当然除了算术元方法外,还有关系元方法,库元方法等等,思想都是一样的,具体可以去看lua的操作手册,下面主要来介绍表操作的元方法。
表的行为可以通过两个元方法改变,一个是__index另一个是__newindex,当我们去索引一个表中不存在的字段时,会得到nil,这是正确的,但是不能说绝对正确,因为当我们索引一个不存在的字段时,其实系统会去查找其元表的__index字段(如果原表存在的话),并以该元表来提供最终结果,看例子:
A={"zhou","long","hui"}
print(A[4])
B={}
B.__index = function() return "this is a nil field" end
setmetatable(A,B)
print(A[4])

通过这两个例子应该很快就理解了.另外由于__index使用很多,从而该元方法不仅仅可以是一个方法,还可以是一个table,当时一个方法时,lua以table和不存在的field作为参数调用该方法,当是一个表时,lua会从该表中继续去索引该字段,并返回对应的值,如下:
A={"zhou","long","hui"}
print(A[4])
B={}
B.__index = {"zhou","long","test","nice!!!"}
setmetatable(A,B)
print(A[4])

类似于__index,当我们给一个表中不存在的字段赋值时,系统就会查找该元方法,如果是一个方法,则调用该方法而不是进行赋值,如果是一个表的话则对元方法的表进行赋值,跟之前索引的表无关,到这里,我们就可以通过这个思想来定义一个只读的table,直接上代码:
function readonly(t)
	local temp = {}
	local mt= {__index = t,
				__newindex = function (t,k,v) error("this is a read-only table") end				
				}
	setmetatable(temp,mt)
	return temp
end

temp = readonly{"z","l","h"}
print(temp[1])
temp[1]="hi!"

跟预期的一样,由于我们的table是只读的,所以引发了错误。

2.小结

通过上面的内容我们对于lua中的元表和元方法已经有了一定的理解,lua中这里的内容的使用很广泛,通过在项目的中不断实践,会有更多的使用的实例,博主水平有限,如有不正确的地方欢迎批评指出。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值