首页 > 代码库 > chapter 13_2 关系类、库定义的元方法

chapter 13_2 关系类、库定义的元方法

  元表还可以指定关系操作符的含义,元方法为__eq ,__lt(小于) ,__le(小于等于).

而其它3个关系操作符则没有单独的元方法,Lua会

把a ~= b 转化为not(a == b)

将a>b   转化为 b < a ;

将a>=b 转化为 b <= a ;

因此需要分别为__le和__lt提供实现:

mt.__le = function(a,b)  --set containment    for k in pairs(a) do        if not b[k] then return false end    end    return trueendmt.__lt = function(a,b)    return a<=b and not(b <= a)end

最后,还可以定义集合的相等性判断:

mt.__eq = function(a,b)  return a <= b and b<=aend

有了这些定义,可以比较集合了:

s1 = Set.new{2,4}s2 = Set.new{4,10,2}print(s1 <= s2 )            --> trueprint(s1 < s2)               --> trueprint(s1 >= s1)            --> trueprint(s1 > s1)               -->falseprint(s1 == s2 * s1)    -->true

等于比较有一点限制,如果两个对象拥有不同的方法,那么等于操作不会调用任何一个元方法,而是直接返回false。

只有当两个比较对象共享一个元方法时,Lua才调用这个等于比较的元方法。

与算术类的元方法不同的是,关系类的元方法不能应用于混合的类型。

如果试图将一个字符串与一个数字作顺序性比较,Lua会引发一个错误。

库定义的元方法

函数tostring,它能将各种类型的值表示为一种简单的文本格式:

print({})            -->table:0x8062ac0

print函数总是调用tostring来格式化其输出。当格式化任意值时,tostring会检查该值是否有一个__tostring的元方法。

如果有这个元方法,tostring就用该值作为参数来调用这个元方法。

这个元方法工作的结果就是tostring的结果。

在集合的实例中,已定义了一个将集合表示为字符串的函数。接下来要做的就是设置元表中的__tostring字段:

mt.__sostring = Set.tostring

此后只要调用print来打印集合,print就会调用tostring函数,进而调用到Set.tostring:

s1 = Set.new{10,4,5}print(s1)        -->{4,5,10}

函数setmetatable和getmetatable也会用到元表中的一个字段,用于保护元表。

假设想要保护集合的元表,使用户既看不到也不能修改集合的元表。那么就需要用到字段__metable。

当设置了该字段,getmetatable就会返回这个字段的值,而setmetatable则会引发一个错误:

mt.__metatable = "not your business"s1 =  Set.new{}print(getmetatable(s1))    -->not your businesssetmetatable(s1,{})        -->stdin:1:cannot change protected metatable

以上内容来自:《Lua程序设计第二版》和《Programming in Lua  third edition 》

chapter 13_2 关系类、库定义的元方法