<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])