Lua学习笔记(八)

来源:互联网 发布:沙龙 陈奕迅 知乎 编辑:程序博客网 时间:2024/06/05 19:07

1.为了理解元表和元方法的概念,通过下面的例子来说明:

假设a和b都是table,通过元表可以定义如何计算表达式a+b。当Lua试图将两个table相加时,它会先检查两者之一是否有元表,然后检查改元表中是否有一个叫__add的字段。如果Lua找到了该字段,就调用该字段对应的值。这个值也就是所谓的元方法,他应该是一个函数

2.在Lua代码中,只能设置table的元表。若要设置其他类型的值的元表,则必须通过C代码来完成。标准的字符串程序为所有的字符串都设置了一个元表,而其他类型在默认情况中都没有元表

3.元表中每种算术操作符都有对应的字段名,__add(加法)、__mul(乘法)、__sub(减法)、__div(除法)、__unm(相反数)、__mod(取模)和__pow(乘幂)。此外,还可以定义__concat字段,用于描述链接操作符的行为

4.在元表中定义操作的步骤:

一.创建一个常规的table,准备用作的元表

二.将上一步创建的table设置为新创建的table的元表

三.将元方法加入元表中

5.当两个集合进行算术类操作时,可以使用任意一个几个的元表。然而,当一个表达式中混合了具有不同元表的值时,Lua会按照如下步骤来查找元表:如果第一个值有元表,并且元表中有对应的字段,那么Lua就以这个字段为元方法,而与第二个值无关;反之,如果第二个值有元表并含有对应的字段,Lua就以此字段为元方法;如果两个值都没有元方法,Lua就引发一个错误

6.元表还可以指定关系操作符的含义,元方法为__eq(等于)、__lt(小于)和__le(小于等于)。而其他三个关系操作符则没有单独的元方法,Lua会将a~=b转化为not(a==b),将a>b转化为b<a,将a>=b转化为b<=a

7."部分有序"是指,对于一种类型而言,并不是所有的值都能排序的。因为存在着一种叫"Not a Number(NaN)"的值。IEEE754标准将NaN视为一种未定义的值,例如0/0的结果就是NaN。标准规定了任何涉及NaN的比较都应该返回false

8.与算术类的元方法不同的是,关系类的元方法不能应用于混合的类型。对于混合类型而言,关系类元方法的行为就是模拟这些操作符在Lua中普通的行为。如果试图将一个字符串与一个数字作顺序性比较,Lua会引发一个错误。同样,如果试图比较两个具有不同元方法的对象,Lua也会引发一个错误

9.等于比较永远不会引发错误。但是如果两个对象拥有不同的元方法,那么等于操作不会调用任何一个元方法,而是直接返回false。这种行为模拟了Lua的普通行为。在Lua的普通行为中,字符串总是不等于数字的,与它们的值无关。另外,只有当两个比较对象共享一个元方法时,Lua才调用这个等于比较的元方法

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

11.假设想要保护集合的元表,使用户既不能看也不能修改集合的元表。那么就需要用到字段__metatable。当设置了改字段时,getmetatable就会返回这个字段的值,而setmetatable则会引发一个错误

12.访问一个table中不存在的字段时,会促使解释器去查找一个叫__index的元方法。如果没有这个元方法,那么访问结果如前所述的为nil。否则,就由这个元方法来提供最终结果

13.__index元方法不必一定是一个函数,它还可以是一个table。当它是一个table时,Lua就以相同的方式来重新访问这个table。而当它是一个函数时,Lua以table和不存在的key作为参数来调用该函数

14.将一个table作为__index元方法是一种快捷的、实现单一继承的方式

15.如果不想在访问一个table时涉及到它的__index元方法,可以使用函数rawget。调用rawget(t,i)就是对table t进行了一个原始的访问,也就是一次不考虑元表的简单访问

16.__newindex元方法与__index类似,不同之处在于前者用于table的更新,而后者用于table的查询

17.若要让具有不同默认值的table都使用同一个元表,那么就需要将每个元表的默认值存放到table本身中。可以使用一个额外的字段来保持默认值。如果不担心名字冲突的话,可以使用"___"这样的key作为这个额外的字段

18.__newindex原理:

      比如如下代码:

      a = {}

      a["x"] = 3

      当a添加新元素x时,会调用__newindex机制,若__newindex方法为函数,则传入三个参数,分别为table(a),下标("x")和索引值(3)。若更改a.x的值,也会调用__newindex。若不声明__newindex机制,则Lua会自动的将a中创建一个新的索引x并赋值为3。采用__newindex的函数方法可以更具灵活性,比如在函数中可以进行跟踪访问的设定

原创粉丝点击