__index:是metatable的一个索引,它的值可以是表或者函数,它的作用是什么呢?举一个栗子:
|
1
2
3
4
5
6
|
local
A = {};local
B = {x=10};B.__index
= B;setmetatable(A,
B);print(A.x); |
打印结果是10,它的查找过程是:首先在表A中查找x,没有找到,继续查找A的元表B,找到元表B的索引__index,此时__index的值是表B,表B是有元素x的,所以打印x的值10。简单总结一下查找表元素的过程:
1. 在表中查找,如果找到,返回该元素,找不到则继续2。
2. 判断该表是否有元表,如果没有元表,返回nil,有元表则继续3 。
3. 判断元表有没有__index,如果__index方法为nil,则返回nil;如果__index的值是一个table,则重复1、2、3;如果__index的值是一个function,则返回该函数的返回值。
__newindex:是metatable的一个索引,跟__index类似,它的值也可以是table或者function,当你给一个不存在的key赋值时,lua会在metatable里查找__newindex。看下面的例子:
|
1
2
3
4
5
6
7
8
9
10
|
local
A = {};local
B = {x=10};B.__newindex
= function(t,
k, v) rawset(t,
k, v);endsetmetatable(A,
B);print(A.y);A.y
= 20;print(A.y); |
第一个print语句,打印是nil,第二个print语句打印出20。__newindex的值在这里是一个函数,有三个参数分别表示:表,键和值。
rawset:可以让你给表的索引赋值时绕过__newindex,如果你在上面的B.__newindex中直接使用t.k = v,会循环调用__newindex产生 stack overflow,rawset可以避免死循环。
rawget:可以绕过__index,如:
print(rawget(A, A.x));
此时打印nil,不会调用元表B的__index。
下面的demo使用lua简单模拟了面向对象的操作。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
local
Animal = { name
= "animal";}function
Animal:eat() print("eat:
"
.. tostring(self.name) );end--new函数负责创建Animal对象。function
Animal:new(name) local
obj = {}; --访问表中不存在的k时会调用__index,此时self就是Animal self.__index
= self; --对表中不存在的k进行赋值时会调用__newindex self.__newindex
= function(t,
k, v) --可以用来设置一些权限操作 if(k
== "sayhello") then print("no
premission"); else --t.k
= v;会发生死循环,出现C
stack overflow rawset(t
,k ,v); end end setmetatable(obj,
self); obj.name
= name; return
obj;endlocal
Bird = { flySpeed
= 10;}--继承Animalsetmetatable(Bird,
Animal);function
Bird:new(name, flySpeed) local
obj = Animal:new(name); obj.flySpeed
= flySpeed; self.__index
= self; setmetatable(obj,
self) return
obj;endfunction
Bird:eat() print("eat:
"
.. tostring(self.name) );endfunction
Bird:fly() print("name="
.. tostring(self.name) .. ";
flySpeed="
.. tostring(self.flySpeed) );endlocal
anim = Animal:new("animal");anim:eat();anim.sayhello
= true;local
bird = Bird:new("bage",
20);bird:eat();bird:fly(); |
运行结果:
eat: animal
no premission
eat: bage
name=bage; flySpeed=20
本文出自:http://codingnow.cn/language/1542.html
本文探讨了Lua中通过表和元表实现面向对象编程的方法,包括__index、__newindex、rawget和rawset的作用,并通过代码示例展示了如何在Lua中模拟面向对象操作。
1565

被折叠的 条评论
为什么被折叠?



