<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 保护元表,不可读写 -- __tostring
3.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])
时间: 2024-11-05 18:30:46