先了解一下关于lua中元表的定义,元表就相当于当前定义了一个表后再将之前定义的一个表设置到当前表中,通过调用当前表中的参数可以查找到之前的表,就可以形成一直简单的元表。下面是一个简单的定义。只是通过两行文字对于元表有一些难以理解,可以先试着看下面的一些方法,或者可以进一步的对于元表有着更好的理解。
element={}
son={}
setmetatable(son,element)
以上就是在son中设置了一个它的元表,我将它命名为element(元表)当有了两个表之后就可以通过setmetatable该函数从而进行设置son的元表,元表没有固定表变量,任何表都可以有自己的元表,当自己有了一个元表之后也可以定义自己的元表。
元表中也有一些关于自己的方法以及特定操作,从而调用自己的元表中的方法以及函数。
element = {
--当子表要被当做字符串使用时 会默认调用这个元表中的tostring方法
__tostring = function(t)
return "元表"
end
}
son = {
name = "本体表"
}
--设置元表函数
--第一个参数 本体表
--第二个参数 元表
setmetatable(son, element)
print(son)
这个就是经过我测试的一个结果,当你输出一个字符串类型的时候就会调用元表中__tostring(这个是两个_)方法然后返回元表的字符串给本体表(本体表只是我个人对他的一个称呼,并不是语言的对他的称呼)。
element = {
--当子表要被当做字符串使用时 会默认调用这个元表中的tostring方法
__tostring = function(t)
return "元表"
end,
--当子表被当做一个函数来使用时 会默认调用这个__call中的内容
--当希望传参数时 一定要记住 默认第一个参数 是调用者自己
__call = function(a, b)
print(a)
print(b)
print("元表")
end
}
son = {
name = "本体表"
}
--设置元表函数
--第一个参数 本体表
--第二个参数 元表
setmetatable(son, element)
--把本体表当做函数使用 就会调用元表的 __call方法
son(1)
将本体表以函数方法的方式进行调用则会触发元表中__call方法,该方法中第一个参数是本体表(但当前本体表中用了字符串所有就调用的元表中的__string方法输出了元表)然后第二个参数是我在son(1)中的1的参数值,然后又输出了元表两个字。以上两个只是元表的一些简单操作,下面开始讲一些特定操作–运算符重载。
element = {
--当子表要被当做字符串使用时 会默认调用这个元表中的tostring方法
__tostring = function(t)
return "元表"
end,
--当子表被当做一个函数来使用时 会默认调用这个__call中的内容
--当希望传参数时 一定要记住 默认第一个参数 是调用者自己
__call = function(a, b)
print(a)
print(b)
print("元表")
end,
--相当于运算符重载 当子表使用+运算符时 会调用该方法
--运算符+
__add = function(t1, t2)
return t1.age + t2.age
end,
--运算符-
__sub = function(t1, t2)
return t1.age - t2.age
end,
--运算符*
__mul = function(t1, t2)
return 1
end,
--运算符/
__div = function(t1, t2)
return 2
end,
--运算符%
__mod = function(t1, t2)
return 3
end,
--运算符^
__pow = function(t1, t2)
return 4
end,
--运算符==
__eq = function(t1, t2)
return true
end,
--运算符<
__lt = function(t1, t2)
return true
end,
--运算符<=
__le = function(t1, t2)
return false
end,
--运算符..
__concat = function(t1, t2)
return "567"
end
}
son = {
age = 2
}
sons = {
age = 4
}
--设置元表函数
--第一个参数 本体表
--第二个参数 元表
setmetatable(son, element)
setmetatable(sons, element)
print(son + sons)
print(son - sons)
print(son * sons)
print(son / sons)
print(son % sons)
print(son ^ sons)
--用条件运算符来比较两个对象
--这两个对象的元表一定要是同一个元表才能准确调用方法
print(son == sons)
print(son > sons)
print(son <= sons)
print(son .. sons)
上述代码就是对两个本体表进行元表的一些算术运算符的一些操作,但这里有一个需要注意的点,就是两个本体表的元表一定要是同一个元表,而且对于不同的算术运算符元表有着不同的方法名称,需要注意的点。可以先试着拿lua歇写一下,加深对于算术运算符的记忆与理解。
接下来就是关乎__index和__newIndex操作的一些介绍
看到上述的代码可能很多会想在元表中不是定义了age属性,但为什么会输出一个nil,这里就有一个很重要的点,__index需要去设置,并不是直接就可以去使用。
son={
}
element={
age=1
}
element.__index = element
setmetatable(son,element)
--__index 当本体表中找不到某一个属性时
--会到元表中找__index指定的表去找属性
print(son.age)
当加了一行代码后它的__index就可以执行了从而在元表中输出我们想要的参数,所以这个点是很重要的。
__index也可以这样直接在元表中进行定义。下面讲一下__newindex的用法
当元表使用了__newindex方法然后setmetatable设置了本体表的元表之后本体表再进行参数的设置则会对__newindex所指向的表进行一些设置,不会对本体表进行设置,从而输出本体表的属性则结果为nil。
当然这个方法没有__index使用的频繁,所有只是简单的了解一下即可。
下面就讲几个小方法,首先是获取本体表的元表,只需要在getmetatable函数的括号中放入本体表即可。
element={}
son={}
setmetatable(son,element)
print(getmetatable(son))
下面再了解一下另一个方法,就是rawget,这个方法的作用是只会在括号中第一个参数的本体表中查找第二个属性参数的值,即使有属于自己的元表也不会去查找。
element={age=1}
son={}
setmetatable(son,element)
--rawget 当我们使用它是 会去找自己身上有没有这个变量
print(rawget(son, "age"))
下面是关于__newindex无法设置的一个函数方法的使用rawset,该方法可以跳过__newindex对它本体表的变量进行修改,从而实现最终的输出。
element={}
element.__newindex = {}
son={}
setmetatable(son,element)
son.age=1
print(son.age)
rawset(son,"age",2)
print(son.age)
rawget是对于__index的使用,rawset是对于__newindex的使用,当你没有使用__index和__newindex方法时,是可以正常的赋值的那么这两个方法也就没有什么作用。
lua的元表也是可以多个表进行连续设置元表,比如这个本体表设置了一个元表,那么也可以在该元表中继续给他设置元表是不会有冲突的。
以上是对lua元表的一个简单介绍以及一些函数方法的使用。