说明
Lua 中的元方法是一组特殊的函数,它们以双下划线开头和结尾(例如 __add、__index、__tostring 等),用于重定义 Lua 中的操作符或操作。通过定义元方法,可以改变 Lua 对象(如表、用户数据等)的行为。
__add
定义对象相加的行为。常用于重载 + 操作符。
示例:
local obj1 = { value = 10 }
local obj2 = { value = 20 }
local mt = {
__add = function(a, b)
return { value = a.value + b.value }
end
}
setmetatable(obj1, mt)
local result = obj1 + obj2
print(result.value) -- 输出 30
__index
定义对表的索引操作的行为,当访问一个表中不存在的索引时触发。常用于实现类似于类的属性访问。
示例:
local obj = { name = "Alice" }
local mt = {
__index = function(table, key)
if key == "greeting" then
return "Hello, " .. table.name
end
end
}
setmetatable(obj, mt)
print(obj.greeting) -- 输出 "Hello, Alice"
__newindex
定义对表的新索引操作的行为,当给一个表中不存在的索引赋值时触发。常用于实现类似于类的属性设置。
示例:
local obj = {}
local mt = {
__newindex = function(table, key, value)
if key == "age" and type(value) == "number" then
rawset(table, key, value) -- 使用 rawset 设置新索引
print("Age has been set to " .. value)
end
end
}
setmetatable(obj, mt)
obj.age = 25 -- 输出 "Age has been set to 25"
obj.age = "invalid" -- 不输出任何信息
__tostring
定义对象转字符串的行为。常用于实现自定义的输出格式。
示例:
local obj = { name = "Bob", age = 30 }
local mt = {
__tostring = function(table)
return "Person: " .. table.name .. ", " .. table.age .. " years old"
end
}
setmetatable(obj, mt)
print(obj) -- 输出 "Person: Bob, 30 years old"
__eq
定义对象相等性的行为。常用于重载 == 操作符。
示例:
local obj1 = { value = 10 }
local obj2 = { value = 10 }
local mt = {
__eq = function(a, b)
return a.value == b.value
end
}
setmetatable(obj1, mt)
setmetatable(obj2, mt)
print(obj1 == obj2) -- 输出 true
__call
定义对象作为函数调用时的行为。常用于将表对象作为可调用函数使用。
示例:
local obj = { value = 5 }
local mt = {
__call = function(table, x)
return table.value * x
end
}
setmetatable(obj, mt)
print(obj(3)) -- 输出 15
__metatable
限制元表的访问,防止修改元表。通过设置元表的 __metatable 字段为一个表,可以限制对元表的访问和修改。
示例:
local obj = {}
local mt = {}
setmetatable(obj, mt)
local protected_mt = { __metatable = {} }
setmetatable(mt, protected_mt)
print(getmetatable(obj)) -- 输出 "{ __metatable = {} }"
setmetatable(mt, {}) -- 尝试修改元表,会触发错误
__len
定义对象的长度操作。常用于重载 # 操作符。
示例:
local obj = { 10, 20, 30 }
local mt = {
__len = function(table)
return #table * 2
end
}
setmetatable(obj, mt)
print(#obj) -- 输出 6
__lt
定义对象的小于(<)操作行为。常用于重载 < 操作符。
示例:
local obj1 = { value = 10 }
local obj2 = { value = 20 }
local mt = {
__lt = function(a, b)
return a.value < b.value
end
}
setmetatable(obj1, mt)
setmetatable(obj2, mt)
print(obj1 < obj2) -- 输出 true
__le
定义对象的小于等于(<=)操作行为。常用于重载 <= 操作符。
示例:
local obj1 = { value = 10 }
local obj2 = { value = 10 }
local mt = {
__le = function(a, b)
return a.value <= b.value
end
}
setmetatable(obj1, mt)
setmetatable(obj2, mt)
print(obj1 <= obj2) -- 输出 true
__pairs 和 __ipairs
定义对象的迭代器行为,允许使用 pairs 和 ipairs 遍历对象。
示例:
local obj = { 10, 20, 30 }
local mt = {
__pairs = function(table)
return ipairs(table)
end
}
setmetatable(obj, mt)
for i, v in pairs(obj) do
print(i, v) -- 输出索引和值
end