接着上一篇博客,继续学习metamethods。按照文档的顺序,接下来是库定义的metamethods。
一.库定义的Metamethods。
简单来说,Lua的很多库都有自己的metatables,在这些metatables定义了许多域,到现在我们看到的metamethods都是Lua核心。虚拟机会不停的检测运行时的值,当这个值涉及到一个操作,这个操作有metatables,并且这些metatables为这个操作定义了metamethods。(这一段是我根据 < Programming in lua,2Nd Edition>翻译的。)
读起来有点拗口,不过比起中文第一版自己觉得还是比较贴切的。
文档上面说了一个例子,print(),我们经常调用print()来输出,我们可以传入字符串参数print(“hello”),也可以传入数值,print(123),也可以传入一个table,print({}),但是都能够输出。这是因为,print()调用了tostring方法,它会把各种类型的参数转换成字符串。以table为例子:
t1 = {
1,2,3,4}
print(t1)
print(tostring(t1))
发现输出的值是一样的,是表t1的地址。tostring会检查t1时候有metatable,如果有metatable会进一步检查是否有__tostring域。如果有则调用,__tostring必须返回一个字符串。我们为它定义一个metatable和__tostring域。然后调用print()输出。
t1 = {
1,2,3,4}
print(t1)
mt = {}
mt.__tostring = function (t)
local s = "{"
for _, k in pairs(t) do
s = s..k.." "
end
return s.."}"
end
setmetatable(t1,mt)
print(t1)
二.表相关的metamethods
我们常说一个表的域,这个域是什么,它可以是表的一个元素,一个函数。比如:
student = {
age = 16,
score = 17,
SetName = function (s,str)
s["name"] = str
end
}
print(student["age"])
print(student["score"])
print(student[