Lua 元表和元方法

元表(Metatable)和元方法(Metamethod)是Lua中实现面向对象编程、操作符重载和自定义行为的重要机制。

元表

元表是一个普通的Lua表,可以附加到另一个表上,用于定义或修改该表的行为。每个表都可以有自己的元表。

|-------------------------------|-------------------|
| setmetatable(tab,metatab) | 将metatab设置为tab的元表 |
| getmetatable(tab) | 获取表tab的元表 |

Lua 复制代码
local t = {}
local mt = {}  -- 元表

-- 设置元表
setmetatable(t, mt)

-- 获取元表
local mt_of_t = getmetatable(t)

元方法

元方法是定义在元表中的特殊键,当表参与特定操作时会被调用。

运算相关元方法

Lua 复制代码
local Calculate = {}

local data1 = {number = 2}
local data2 = {number = 4}

setmetatable(data1,Calculate)
setmetatable(data2,Calculate)

--加
Calculate.__add = function(a,b)
   return a.number+b.number
end
print(data1 + data2)

--减
Calculate.__sub = function(a,b)
   return a.number-b.number
end
print(data1 - data2)

--乘
Calculate.__mul = function(a,b)
   return a.number*b.number
end
print(data1 * data2)

--除
Calculate.__div = function(a,b)
   return a.number/b.number
end
print(data1 / data2)

--取余
Calculate.__mod = function(a,b)
   return a.number%b.number
end
print(data1 % data2)

--等于判断
Calculate.__eq = function(a,b)
   return a.number == b.number
end
print(data1 == data2)

--连接符
Calculate.__concat = function(a,b)
   return a.number .. b.number
end
print(data1..data2)

--小于号
Calculate.__lt = function(a,b)
   return a.number < b.number
end
print(data1<data2)

--小于或等于
Calculate.__le = function(a,b)
   return a.number <= b.number
end
print(data1 <= data2)

--幂运算
Calculate.__pow = function(a,b)
   return a.number ^ b.number
end
print(data1 ^ data2)

--负数
Calculate.__unm = function(a)
   return -a.number
end

print(-data1)

测试打印:

库定义相关元方法

__tostring

当要打印表名时,Lua就会查找该表的元表中的__tostring方法,并调用;将对象作为参数传给该函数,然后把元方法的返回值返回。

Lua 复制代码
local animal = {
   name = "动物"
}

local cat = {
   name = "小猫咪"
}

setmetatable(cat,animal)

animal.__tostring = function(t)
   print(t.name)
   return "动物方法"
end

print(cat)

__call

当表被当做一个函数被调用时,Lua就会查找该表的元表中的__call方法,并调用

Lua 复制代码
local animal = {
   name = "动物"
}

local cat = {
   name = "小猫咪"
}

setmetatable(cat,animal)

animal.__call = function(t)
   print("我是"..t.name.."的方法")
end

cat()

表相关元方法

__index

当访问一个表中不存在的字段时,那么Lua就会寻找该table的metatable中的__index 键

元方法是一个表

Lua 复制代码
local Human = {}
Human.__index = {
   score = 250
}
local Student = {}

setmetatable(Student,Human)
print(Student.score)

元方法是一个函数

Lua 复制代码
local Human = {}
Human.__index = function()
   print("调用index元方法")
   return 1000
end
local Student = {}
setmetatable(Student,Human)
print(Student.score)

__newindex

当给表中一个不存在的键赋值时,首先判断该表是否有元表,如果没有则相当于直接在表中声明一个变量并赋值,如果有则在元表中查找__newindex键,如果__newindex包含一个表则直接在该表中赋值,不在原始表中赋值。

__newindex 元方法用来对表更新,__index则用来对表访问 。

rawset

在不触发元方法__newindex的情况下,在原始表中进行声明赋值.

未用rawset情况:如果直接赋值的话,会查找tab2的元表中的元方法__newindex,将在元表tab1中声明该键并赋值,而不在tab2中声明赋值

使用rawset情况:当元表中有元方法__newindex时,使用rawset,给tab2中的不存在的键赋值,不会调用元方法__newindex,直接在tab2中声明赋值

rawget

在不触发元方法__index的情况下,直接在原始表中查找该字段

Lua 复制代码
local Human = {
  score = 100
}

Human.__index = {
   score = 250
}

local Student = {}
setmetatable(Student,Human)
print(rawget(Student,"score"))
相关推荐
wcjwdq12 小时前
Lua和JS的继承原理
javascript·lua·脚本继承
哈哈哈哈哈哈哈哈哈...........16 小时前
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
tcp/ip·nginx·lua
程序猿多布4 天前
Unity使用Lua框架和C#框架开发游戏的区别
unity·c#·lua
chiou7224 天前
为 Ubuntu 安装的软件创建桌面图标
linux·ubuntu·lua
黄暄4 天前
分布式锁优化:使用Lua脚本保证释放锁的原子性问题
java·redis·分布式·后端·junit·lua
泉飒4 天前
lua注意事项
开发语言·笔记·lua
先做个垃圾出来………4 天前
接口自动化常用断言方式
数据库·自动化·lua
Clownseven5 天前
Nginx Lua模块(OpenResty)实战:动态化、智能化你的Nginx,实现复杂Web逻辑 (2025)
nginx·lua·openresty
会敲键盘的猕猴桃很大胆5 天前
Redis实战-基于redis和lua脚本实现分布式锁以及Redission源码解析【万字长文】
java·redis·分布式·spring·lua
JAdroid6 天前
spring-boot redis lua脚本实现滑动窗口限流
数据库·spring boot·redis·spring·lua·redisson