--元表:元表是用来存放对table操作方式的表,当要对一个表进行各种操作(查询,加减等)就会到它的元
-- 表找到对应的元方法,元方法存放要获取数据和操作方法
--"元方法": __add, __sub,__mul,__div,__eq(等于),__lt(小于),__le(小于等于)
-- __unm(相反数)、__mod(取模)、__pow(乘幂)、__concat(连接操作符)
-- __tostring(print时调用) ,__metatable(设置后不可修改元表)
print("----------------")
--第1步: 定义“原始表”
tab_1={10,20,50}
tab_2={35,70,80}
tab_3={num1=10,num2=20,num3=50}
tab_4={num1=50,num2=60,num3=8}
--测试
--tabRes=tab_1+tab_2 --两个表直接做算数运算,会导致报错。
--第2步: 定义“元表”(核心计算)
setTable={} --定义一个“元表”
--定义“元表”的加法函数
-- 参数:
-- tab1 是原始表1, tab2 是原始表2
function setTable.Adding(tab1,tab2)
local addTableRes={} --返回结果表
for i, v in pairs(tab1) do
if(v==nil) then
break
end
addTableRes[i]=tab1[i]+tab2[i]
end
return addTableRes
end
--定义“元表”的减法函数
-- 参数:
-- tab1 是原始表1, tab2 是原始表2
function setTable.Sub(tab1,tab2)
local subTableRes={} --返回结果表
for i, v in pairs(tab1) do
if(v==nil) then
break
end
subTableRes[i]=tab1[i]-tab2[i]
end
return subTableRes
end
----第3步: 设置元方法
setTable.__add=setTable.Adding --Adding函数,作为“__add” 的实际执行的元方法
setTable.__sub=setTable.Sub
--第4步: 设置元表
setmetatable(tab_1,setTable)
--setmetatable(tab_2,setTable)
setmetatable(tab_3,setTable) --测试“键值对”类型的表
--setmetatable(tab_4,setTable)
--第5步: 测试输出
tabResult1=tab_1+tab_2 --测试表之间的“加法”
tabResult2=tab_1-tab_2 --测试表之间的“减法”
tabResult3=tab_3+tab_4 --测试表之间的“加法”(属于键值对类型的table)
----输出结果
for i = 1, #tabResult1 do
print(tabResult1[i])
end
for i = 1, #tabResult2 do
print(tabResult2[i])
end
----输出结果(表是键值对类型)
for i, v in pairs(tabResult3) do
print(i,v)
end
print("----------------")
--[[-
--第1步: 定义“原始表” ]]
--tab_1={10,20,50,300,200}
tab_2={str1="Unity脚本",str2="C#语言",str3="Lua语言"}
--测试
--print(tab_1) --没有定义“元方法”无法直接打印
--print(tab_2)
----第2步: 定义“元表”(核心计算)
local setTable={}
----设置直接打印的元方法
----参数:tab
---- 表示需要进行处理的“原始表”
function setTable.ToString(tab)
local tabResult={} --返回结果表
for i, v in pairs(tab) do
--开始#tabResult=0,循环中长度慢慢增加
tabResult[#tabResult+1]=v
end
return table.concat(tabResult, ",")
end
----第3步: 设置元方法
setTable.__tostring=setTable.ToString
--规定tab_2的元表不允许被修改成其他元表和获取(不能使用getmetatable获得元表 )
setTable.__metatable="不能修改受保护的元表('Don't modify protected metatable !')"
----第4步: 设置元表
setmetatable(tab_2,setTable)
------第5步: 测试输出
print(tab_2)
--测试, 再次做设置元表
--setmetatable(tab_2,{})
--print(getmetatable(tab_2))
--print("测试修改元表后的输出结果: ")
--print(tab_2)
--Table访问元方法
--__index(查询table):当访问一个table中不存在的字段时,会促使解释器去元表查找一个叫__index的元方法.
--如果没有这个元方法,那么访问结果就是nil,否则就由这个元方法来提供最终的结果。
--__newindex(给table新字段赋值):
--当对一个table中不存在的索引赋值时,解释器就会查找元表的__newindex元方法。
--如果有这个元方法,解释器就调用它,而不是执行赋值。
------__index
tabTable={str1="师长",str2="军长"}
--定义元表核心函数
local setTable={}
--提示信息
function setTable.tipNotFinding()
return "您查询Table中没有对应的记录!"
end
function tipNotFinding()
return "您查询Table中没有对应的记录!"
end
--设置元方法
setTable.__index=setTable.tipNotFinding
---设置原始表对应的元表
--setmetatable(tabTable,setTable)
--(简化形式)
setmetatable(tabTable,{__index=tipNotFinding})
--
setmetatable(tabTable,{ __index={ str3="abcd" } })
----测试
print(tabTable["str1"]) --output: “师长”
print(tabTable["str5"]) --output: nil
print(tabTable["str3"]) --output: abcd
-------__newindex
--[[--学习Table访问的元方法: “__newindex”元方法(作用: 给一个表新字段赋值,触发本元方法)]]
tabTable={str1="科长",str2="处长"}
--定义元表的实现函数
function AddValue(tab,k,v)
print("检测到你给Table添加了新的数据 k="..k.." v="..v)
end
--定义元表元方法
setmetatable(tabTable,{__newindex=AddValue})
----测试
print(tabTable["str1"]) --output: “科长”
tabTable["str3"]="厅长" --添加了元方法 ,添加元素没成功
print(tabTable["str3"]) --output: "厅长"
--[[--学习Table访问的元方法: “__newindex”元方法
增加学习 "rawset()" 函数]]
tabTable={str1="科长",str2="处长"}
--定义元表的实现函数
function AddValue(tab,k,v)
--rawset(t,k,v)方法可以绕过元方法直接对table进行赋值。配合“__newindex”元方法一起使用
--元表函数继续执行。
rawset(tab,k,v)
print("检测到你给Table添加了新的数据 k="..k.." v="..v)
end
--定义元表元方法
setmetatable(tabTable,{__newindex=AddValue})
--测试
print(tabTable["str1"]) --output: “科长”
tabTable["str3"]="厅长" --给一个Table 新字段赋值,是成功的。
print(tabTable["str3"]) --output: "厅长"
--[[--学习Table访问的元方法: “__newindex”元方法, 再次举例]]
myTable=setmetatable(
{key1="Value"},
{
__newindex=function(mytable,key,value)
rawset(myTable,key,"---"..value.."----")
print("__newindex 核心处理函数被执行了")
end
}
)
myTable.key1="new Value"
myTable.key2=88
----测试输出
print(myTable.key1,myTable.key2) --output: new value 88
--[[--学习Table 访问元方法:'__call']]
---- __call (调用表的时候使用):
--原始表
tab1={}
--元表核心处理函数
function InvokeMethod()
print("本元表被调用")
end
----设置元表元方法
setmetatable(tab1,{__call=InvokeMethod})
--测试
--表加括号
print(tab1()) --相当于一个Table 被执行。即: 就是元方法核心处理函数,成为了表中的一个函数。
--原始表
tab1={10,20}
--元表核心处理函数
function InvokeMethod(tab,num1,num2)
print("本元表被调用")
return num1+num2
end
--设置元表元方法
setmetatable(tab1,{__call=InvokeMethod})
--测试
-- 表被当做方法来调用
print("调用的结果=",tab1(tab1[1],tab1[2]))