lua中对于metatable用法和原理的总结
2014-12-28 14:30
323 查看
<span style="font-family: Arial, Helvetica, sans-serif;">-- --metatable 可以作为继承的用法</span>
parent = { house = 1 } parent.__index = parent --如果没有这一句话 child即使是设置parent为元表 也不能找到parent中的内容. __index指向的内容是nil child = { wife = 2 } setmetatable(child, parent) print(child.house) print(child.wife) parent.__newindex = function ( t, k ,v ) -- t[k] = v if k == "house" then parent[k] = v * 2 end end -- 等效于 -- parent.__newindex = parent child.house = 3 child.wife = 4 print(child.house) print(child.wife) parent.__index = nil child.house = 5 child.wife = 6 print(child.house) print(child.wife) --打印结果是: -- 1 -- 2 -- 6 -- 4 -- nil -- 6
2.metatable可以类似c++中重载操作符(重写元方法)
f1 = { a = 1, b = 2 } f2 = { a = 2 , b = 3 } -- s = f1 + f2 现在的f1 和 f2 没有各自的__add函数 meta = {} function meta.__add(f1, f2) local sum = {} sum.a = f1.a + f2.a sum.b = f1.b + f2.b return sum end setmetatable(f1, meta) setmetatable(f2, meta) s = f1 + f2 print(s.a) print(s.b) --需要重载的操作符 --算数类型 -- __add(a, b) for a + b -- __sub(a, b) for a - b -- __mul(a, b) for a * b -- __div(a, b) for a / b -- __mod(a, b) for a % b -- __pow(a, b) for a ^ b -- __unm(a) for -a -- __concat(a, b) for a .. b -- __len(a) for #a --关系类型 -- __eq(a, b) for a == b -- __lt(a, b) for a < b -- __le(a, b) for a <= b --table访问的元方法 -- __index(a, b) <fn or a table> for a.b -- __newindex(a,b) -- __newindex(a, b, c) for a.b = c -- __call(a, ...) for a(...) -- 库定义的元方法 -- __metatable 保护元表,不可读写 -- __tostring3.metatable 可以当成一个类来使用
Parent = {} function Parent:new() local newParent = { house = "white house" } self.__index = self return setmetatable(newParent, self) end function Parent:Wife( ) print("mother live in the "..self.house ) end parent = Parent:new() parent:Wife() --通过类似类的方式来继承 Child = Parent:new() function Child:Position() local ChildHouse = self.house print("child live in the "..ChildHouse) self:Wife() end child = Child:new() child:Position() -- lua中检查某值得顺序:比如child 的house 属性。 先到Child中去检查有没有某个字段。就会去检索__index这个元方法。 -- 即当需要访问一个字段在table中不存在的时候,解释器会去查找一个叫__index的元方法,如果没有该元方法,那么访问结果就是nil,不然就由这个元方法来提供最终结果。 test1 = { param1 = 1} test2 = { param2 = 2} test3 = { param3 = 3} -- test2.__index = test1 等价于: test2.__index = function(testTable , key) -- print(testTable) -- print(test3) -- print(key) -- print(test1[key]) return test1[key] end setmetatable(test3 , test2) print(test3.param1) print(test3.param2) print(test3.param3) -- 这里的__index赋值就相当于 test2.__index = test1 --注释部分打印得出的结果是: -- table: 0x7fe038c05440 -- table: 0x7fe038c05440 -- param1 -- 1 -- nil -- table: 0x7fe038c05440 -- table: 0x7fe038c05440 -- param2 -- nil -- nil -- 3 --testTable的地址和test3的地址相同 ,由此可知,__index这种元方法会有一个默认形参是该表本身。而这里setmetatable只是给表设置了元表,真正查询字段的是根据元表中__index元方法所指向的表中的字段。而不是元表中的字段。
这里有个问题没有搞清楚,多打印出来一个nil这个nil是什么? 如果有理解的同学请在下面留言,指点我一下。
4.metatable的结合应用
--具有默认值的应用 function setDefault (mainTabel , returnValue) local mt = {__index = function () return returnValue end } setmetatable(mainTabel , mt) end tab = { x = 10 ,y = 20} print(tab.x , tab.y , tab.z) setDefault(tab, 0) print(tab.x , tab.y , tab.z) --只读属性的table function readOnly (t) local proxy = {} local mt = { __index = t, __newindex = function (t, k ,v) print("it's a readOnly table ") end} setmetatable(proxy , mt) return proxy end days = readOnly { 1 , 2 ,3 ,4 ,5 ,6 ,7} print(days[1]) days[2] = 12 -- print(days[2])
相关文章推荐
- lua中metatable源码分析总结
- Lua学习之metatable总结
- 对于C++中的const用法的总结
- bufferreader与bufferwrite以及用法与readline()方法原理自述总结
- 关于Java泛型实现原理的思考与一般用法示例总结
- Java反射机制概念、原理与用法总结
- NSPredicate用法总结(Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取)
- iOS开发:个人对于textView基础用法的总结(其一)
- Java内部类原理与用法实例总结
- 对于 const 用法总结
- STL中next_permutation用法小结和小技巧总结与原理。
- String的原理与用法总结
- C++编译器对于多态的实现原理总结
- Insert Into的用法总结
- 对于多态性的学习总结---虚函数的有与没有
- css中*的新用法(对于我而言)和对+的解释
- 枚举类型的一些用法总结
- 模式窗口showModalDialog的用法总结
- xDoclet在Hibernate中的用法总结
- oracle学习总结三(bulk collect用法)