首页 > 技术文章 > lua 面向对象

sevenmoons 2018-03-12 18:05 原文

云风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

 

推荐阅读