setmetatable()和getmetatable():
local a=8
local b = "s"
local t = {1,2}
--在Lua代码中,只能设置table的元表。若要设置其它类型的值得元表,则必须通过C代码来完成
--对于字符串,标准的字符串程序库为所有的字符串都设置了一个元表,而其它类型在默认情况下都没有元表
print(getmetatable(t)) --输出nil
print(getmetatable(b)) --输出table: 0042EA68
print(getmetatable(a)) --输出nil
local t2 = {}
setmetatable(t,t2) --将t2设置为t的元表
print(getmetatable(t)) --输出table: 0026B120
--setmetatable(a,t2)
--print(getmetatable(a)) --报错 /在 Lua 代码中,通过调用setmetatable 来设置且只能设置 table 的元表
setmetatable(b,t2)
print(getmetatable(b)) --报错 /在 Lua 代码中,通过调用setmetatable 来设置且只能设置 table 的元表
元方法__metatable:
Set = {}
local mt = {}
--根据参数列表中的值创建一个新的集合
function Set.New(T)
local set = {}
setmetatable(set,mt)
for _ ,v in pairs(T) do
set[v]=true
end
----使用__metatable可以保护元表,禁止用户访问元表中的成员或者修改元表
mt.__metatable = "can not get the metatable"
return set
end
local tb = Set.New({1,2,3}) --将mt设置为tb的元表
print(tb)
print(getmetatable(tb)) --输出can not get the metatable
local test = {1,2}
setmetatable(test,mt)
print(getmetatable(test)) --输出can not get the metatable
--setmetatable(tb,{}) --报错cannot change a protected metatable 输出"can not get the metatable"
元方法__add:
--------------元方法 __add
local mt ={}
--定义一个元方法
mt.__add = function (t1,t2)
local temp = {}
for i, v in pairs(t1) do
table.insert(temp,v)
end
for i, v in pairs(t2) do
table.insert(temp,v)
end
return temp
end
local t1 = {1,2,3}
local t2 = {3,5}
setmetatable(t1,mt) --设置mt为t1的元表
local t3 = t1+t2 --将两个table相加
for i, v in pairs(t3) do
print(v) --输出1 2 3 3 5
end
--程序执行顺序:
--lua中两个table原本是无法做相加操作的,但是可以通过__add元方法实现
--先查询t1中是否有对应的元表,若有看看是否定义了__add元方法。如果有则运算
--没有则查询t2中是否有对应的元表,再看看是否定义了__add元方法,有则运算,没有报错
元方法__index:
---
windows = {}
windows.default = {x=0,y=0,color = {r=255,g=255,b=125}}
windows.mt = {} --创建元表
--声明new函数
function windows.new(o)
setmetatable(o,windows.mt)
return o
end
--定义__index元方法 对应的是一个有参数的函数
windows.mt.__index = function(table,key)
return windows.default[key]
end
local www = windows.new({x=10,z=30})
--print(www.x) --输出10
--print(www.y) --输出 0
--print(www.color.r) --输出 255
other1 = {hhh = 666}
other2 ={mmm=333,ppp=999,hhh=5555}
setmetatable(other2,other1)
--定义__index元方法 对应的是一个table
other1.__index =other1
print(other2.hhh) --输出666
print(other2.jjj) --输出nil
--定义__index元方法 对应的是一个没有参数的函数
--function setDefault(tb,defaultValue)
-- local mt = {__index = function()return defaultValue end}
-- setmetatable(tb,mt)
--end
--tb1 = {x=10,y=20}
--setDefault(tb1,100)
--print(tb1.x) --输出 10
--print(tb1.z) --输出100
--print(tb1.k) --输出100
--程序执行顺序:
--通过键来访问table时,如果table中没有这个键,那么lua就会查找该table是否有元表
--元表中是否定义了__index元方法,若__index对应的是一个函数,那么lua就会调用这个函数,
--table和键作为参数传给函数;
--若__index对应的是一个table,那么lua就在这个table中查找对应的键
元方法__newindex:
---
local smartMan = {
name = "king",
sayhello = function()
print("你妈喊你回家吃饭")
end
}
local t1 = {kkk = "7"}
--t1.name = "5"
local mt ={
--__index = smartMan,
__newindex = function(table,key,value)
print("你妈喊你回家拖地")
rawset(table,key,value)
end,
}
setmetatable(t1,mt)
t1.kkk = 6
print(t1.kkk) -- 输出 6
t1.kkk = "5"
t1.ggg = "000" --新增一个索引
print(t1.kkk) --输出 你妈喊你回家拖地 5
-- __newindex元方法用于索引更新
rawget()和rawset():
--rawset(table,index,value)
--在不调用元表的情况下,给table[index]赋值为value
--就是说就算该table有元表,这个函数也会让元方法失去作用
local m1 = {x=1,y=2}
local m2 = {z=3}
setmetatable(m1,m2)
m2.__index = m2
print(m1.z) --输出3
rawset(m1,"z",5)
print(m1.z) --输出 5
--rawget(table,index)
--不调用元表,获取table真正的值table[index]
local m3 = {x=1,y=2}
local m4 = {x=6,z=8}
setmetatable(m3,m4)
m4.__index = m4
print(m3.x) --输出 1
print(m3.z) --输出 8
local zhi= rawget(m3,"z")
print(zhi) --输出nil
元方法总汇:
后续若有在项目中碰到其他元方法再补上。