我们都知道在高级语言中自定义的类的俩个变量如果要完成相加操作就需要重载+操作符,通过重载ToString方法来改变对象的输出方式,在lua中完成类似这样的操作靠的是元表,元表可以扩展或者改变变量的操作方式。lua的元表很重要,借助元表可以完成一些高级的操作,下面是使用方式。

--[[  所有的table类型变量和userdata类型的变量都可以有属于自己的一个元表,而其他类型的值共享该类型对应的一个元表 
通过getmetatable可以获得该变量对应的元表,除了string类型的变量其他的类型变量都得到的是nil,就是说默认是没有元表的,而系统为string类型的值预先设置了一个元表
--]]
local t1 = {};
print(getmetatable(t1));
local i = 10;
print(getmetatable(i));
local t2 = {};
--[[- 只能通过setmetable为table类型的值设置元表,其他的值元表的设置需要在c语言中完成 -]]
setmetatable(t1,t2);
print(getmetatable(t1));

--[[ 以下俩个值打印的元表是相同的,说明所有的字符串值共享一个元表 --]]
print(getmetatable("hello world"));
print(getmetatable("xiaota"));

local t3 = {1,2};
local t4 = {3,4};
setmetatable(t3,t2);
setmetatable(t4,t2);
--[[-我们称元表中的键为事件(event),称值为元方法(metamethod)。-]]
t2.__add = function(a,b)
  --执行相关的操作
  end
--[[
1对于二元操作符,如果第一个操作数有元表,并且元表中有所需要的字段定义,比如我们这里的__add元方法定义,那么Lua就以这个字段为元方法,而与第二个值无关;
2对于二元操作符,如果第一个操作数有元表,但是元表中没有所需要的字段定义,比如我们这里的__add元方法定义,那么Lua就去查找第二个操作数的元表;
3如果两个操作数都没有元表,或者都没有对应的元方法定义,Lua就引发一个错误。--]]

--[[当你通过键来访问table的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的 __index 键。如果 __index 包含一个表格,Lua会在表格中查找相应的键。__index键对应的值可以是一个方法或者是一个表 --]]
t2.__index = {xiao="xiao",ta="ta"};
print(t3.xiao);
print(t3[1]);

--__call 使得你可以像调用函数一样调用table
t2.__call = function(t,a,b,c)
  return a+b+c;
end

t2.__tostring = function()
  return "xiaotablog";
  end

print(t3(1,2,3)); --6
print(t3); --xiaotablog

Lua基础学习七——元表

local mt = {};
--setmetatable 返回第一个参数
local t = setmetatable({xiao="xiao"},mt);
--__newindex用于给元表赋值的情况
mt.__newindex = {};

--原始表中存在这个索引,则改变索引对应的值
t.xiao = "hello";
print(t.xiao);
print(mt.__newindex.ta);

--若不存在这个索引,则查看是否有元表,元表中是否有__newindex这个事件,如果有就调用这个方法或者是设置对应表中的值
t.ta = "world";
print(t.ta);
print(mt.__newindex.ta);

--以下的代码会出现死循环
local tb1 = {}
local tb2 = {}
tb1.__newindex = tb2
tb2.__newindex = tb1
setmetatable(tb1, tb2)
setmetatable(tb2, tb1)
--tb1.x = 10

--rawset rawget获得和设置原始表的值,和元表无关,避免了上面的死循环
rawset(tb1,"x",1)
print(rawget(tb1,"x"));