Chinaunix首页 | 论坛 | 博客
  • 博客访问: 461269
  • 博文数量: 107
  • 博客积分: 6073
  • 博客等级: 准将
  • 技术积分: 790
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-14 15:34
文章分类

全部博文(107)

文章存档

2010年(1)

2009年(106)

分类:

2009-08-18 15:52:18

Lua中元表(metatable)是一个非常强大的功能,它使lua的设计看起来更面向对象一些。而元表中元方法包含了一组预定义的操作,
就像C++中重载操作符一样。

元方法中的关系类的元方法是一组指定的关系操作符,包含有3个,分别是:__eq(等于), __lt(小于), __le(小于等于)。
另外三个操作:不等于,大于,大于等于将会被lua自动转换。如下: a~=b -> not a==b, a>b -> b=b -> b<=a 。

lua 4.0 以前在这里存在一个错误,因为它忽略了NaN(Not a Number)的值,这个值的含义是为定义,比如 0/0 就会得到该值。
之前的lua会把顺序操作符都转化为小于操作 a>=b --> not (a <> P116-P117,或其他书籍。

在这里,我想解释的是 "如果试图比较两个不同元方法的对象,Lua也会引发一个错误"。(P117)
在算术元方法中,只要其中一个对象拥有适用的元方法,就会被调用,但是关系比较中,这样却会引发一个错误。
其他这个很容易理解,就像C/C++语言中数字的大小比较和字符串的大小比较是不同的方法。用一个数字和一个字符串比较就会引发一个错误。
注意是字符串,不是字符。我当然知道字符与数字比较时会被自动转换为ASCII码值。。。

问题1:元方法采用的一样的实现,会错误吗?
问题2:元方法再两次引用之间,出现了变动,Lua是否能检查出来。
let's GO!
-- 测试代码 1 +注释------------------------------------------------------------
function lt1(s1, s2)
     return true
end

function lt2(s1, s2)
     return true
end

mt1 = {}     -- 定义元表一
mt2 = {}     -- 定义元表二
mt1.__lt = lt1   -- 定义元表一的小于操作
mt2.__lt = lt2   -- 定义元表二的小于操作

t1 = {}     -- 对象一
t2 = {}     -- 对象二
setmetatable(t1, mt1)   -- 设置对象一的元表
setmetatable(t2, mt2)   -- 设置对象二的元表

-- 上面的代码的含义就是,定义了t1,t2两个对象,t1的小于操作的实现是函数lt1(),
-- t2的小于操作的实现是函数lt2(),两个函数的实现是一样的。(都不采取任何操作)
--
if (t1 < t2) then       -->错误,看来即使是一样的实现也是不行的。
end

-- 测试代码 2 +注释-------------------------------------------------------------------
function lt1(s1, s2)
     return true
end

mt1 = {}     -- 定义元表一
mt2 = {}     -- 定义元表二
mt1.__lt = lt1   -- 定义元表一的小于操作

function lt1(s1, s2)
     return false
end

mt2.__lt = lt1   -- 定义元表二的小于操作,都指向了函数lt1,但之前被重新定义了
t1 = {}     -- 对象一
t2 = {}     -- 对象二
setmetatable(t1, mt1)   -- 设置对象一的元表
setmetatable(t2, mt2)   -- 设置对象二的元表

-- 上面的代码的含义就是,定义了t1,t2两个对象,t1的小于操作的实现是函数lt1(),
-- t2的小于操作的实现是也是函数lt1(),不过前后的lt1函数有变动。
--
if (t1 < t2) then       -->错误,lua仍然认定t1 和 t2 的小于操作不是同一个方法。
end

-----------------------------------------------------------------------------------------
为什么呢?
答案:lua中函数是匿名的。函数名只是对实际函数的一个引用。lua中通过函数的地址,来判断是不是调用的同一个函数
第一个测试中,定义的两个函数,肯定不对。
第二个测试中,虽然函数名一样,但是却是两个不同的函数的引用。
所以"如果试图比较两个不同元方法的对象,Lua也会引发一个错误"。(P117)
阅读(1374) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~