元表与元方法
在学习table的时候已经提到这两个概念。其实,可以把这两个概念和C++中的运算符重载进行比较,
在功能上确有相似性。例如,C++中自定义的类型不能进行数学运算,但是我们可以重载运算符就可以
进行数学运算操作。Lua中就是用元表和元方法来实现这个功能的。
Lua中的 table 都可以有元表,我们可以用 getmetatable 这个函数来得到一个 table 的元表,
可以用 setmetatable 这个函数来设置一个 table 的元表。
t = {}
print(getmetatable(t)) --> niltable默认元表是空的,可以通过setmetatable 函数来改变其元表。
t1 = {}
setmetatable(t, t1)
print(getmetatable(t) == t1) ---> true表的行为都是通过元方法来实现的,元方法主要分为以下几种:
一、算术运算的元方法
1. __add 对应 + 运算,只要我在元表中实现 __add 方法就能对表进行加操作。
2. __mul 对应 * 运算,只要我在元表中实现 __mul 方法就能对表进行加操作。
3. __sub 对应 - 运算,只要我在元表中实现 __sub 方法就能对表进行加操作。
4. __div 对应 / 运算,只要我在元表中实现 __div 方法就能对表进行加操作。
5. __unm 对应 - ( 求相反数运算)运算,只要我在元表中实现 __unm 方法就能对表进行加操作。
6. __pow 对应 + 运算,只要我在元表中实现 __pow 方法就能对表进行加操作。
另外,还可以定义 __concat 字段,用于描述连接操作符的行为。当然这些方法要在元表中定义。
Set = { }
function Set.union (a, b)
local res = Set.new{ }
for k in pairs(a) do
res[k] = true
end
return res
end
local mt = { }
mt.__add = Set.union
function Set.new( l )
local set = { }
setmetatable( set, mt )
for _, v in ipairs( l ) do
set[ v ] = true
end
return set
end
上面的代码演示了如何让两个 table 也能相加的操作。其他操作类似,都是把元表中的相对应字段与自定义的
行为相关联即可。
二、关系类的元方法
能够定义元方法的关系操作符有 ==、< 和 <= ,其他三个关系操作符没有单独的元方法,
而是通过转化来实现的,如 a ~= b 转化为 not ( a == b )。
对应的元方法为:__eq ( 等于 )、__lt ( 小于 ) 和 __le ( 小于等于 ).
实现方法和算术类元方法类似。
三、库定义的元方法
1. tostring 它能将各种类型的值表达为一种简单的文本格式。
四、table访问的元方法
前面已经介绍了table行为的一些元方法,如:__index 和 __newindex
1. __index 元方法
当检索 table 中不存在的字段时会调用这个方法。
我们可以把 __index 定义为一个函数,也可以定义为一个 table, 当定义为一个 table 时,
lua 会在该 table 中查找 __index 方法。
2. __newindex元方法
__newindex 和 __index 类似,它是在给 table 中不存在的字段赋值时调用,其他用法都一样。
通过元表和元方法,我们可以写出很复杂的功能,Lua 中的面向对象就是通过这两个技术来实现的。
















