云风lua面向对象代码分析
必须在先了解__index与_newindex
__index:在表中查找键不存在时转而在元表中查找键值的功能,只在调用时才会运行,需要有return值;
mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return "test"
end
end
})
print(mytable.key1,mytable.key2)
运行结果是value1 metatablevalue,当key1存在时,不会进入__index元方法
__newindex:当访问的键在表中不存在时,此时添加新键值对的行为将由此元方法(newindex)定义。
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "new value 2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "new value 1"
print(mytable.key1,mymetatable.newkey1)
运行结果是
value1
nil new value 2
new value 1 nil
setmetatable(mytable, {
__newindex = function(mytable, key,value)
print("运行key2")
end
})
mytable[1] = 20
向一个不存在的键赋值,运行结果是 运行key2
这里的__newindex是一个表,如果键存在于主表中,只会简单更新相应的键值。而如果键不在表中时,会在另外的表 mymetatable 中添加该键值对。如果是一个方法,像下面的例子一样,就不会在该类中调用没有方法,转而运行父类中的方法
///_class来索引各个类(class_type)的对应的vtbl(里面记录了该类的成员变量和成员方法,通过__newindex元方法来实现),修改的都是vtbl表,
local _class={}
function class(super)
local class_type={}
class_type.ctor=false
class_type.super=super
class_type.new=function(...)
//构造方法,不断向上查询,
local obj={}
do
local create
create = function(c,...)
if c.super then
create(c.super,...)
end
if c.ctor then
c.ctor(obj,...)
end
end
create(class_type,...)
end
////把对象实例跟vtbl表绑定;
setmetatable(obj,{ __index=_class[class_type] })
return obj
end
local vtbl={}
_class[class_type]=vtbl
///////在调用该类时,方法都通过__newindex拦截查询,在下面print(key) 时可以看到只要require了该类,就会打印出该类的所有方法
setmetatable(class_type,{__newindex=
function(t,k,v)
print(k)
vtbl[k]=v
end
})
/////如果该类有父类,方法会先通过__newindex查询,如果有就不会执行以下__index方法,如果没有,才会向父类查询
if super then
setmetatable(vtbl,{__index=
function(t,k)
local ret=_class[super][k]
vtbl[k]=ret
return ret
end
})
end
return class_type
end