🧩 一、先说结论:Lua本身没有"类"
很多人学到这里会懵:
- ❌ 没有 class
- ❌ 没有继承
- ❌ 没有封装
但却能写出完整的面向对象系统?
👉 答案只有一个:
🔥 元表(Metatable)
🧠 二、元表到底是什么?(用人话讲清楚)
你可以把元表理解为:
👉 "Table的行为控制器"
或者更直白一点:
👉 当你访问一个Table时,如果找不到,就去问元表
🚀 三、最关键机制:__index(核心中的核心)
我们直接上代码👇
🎯 1. 一个最简单的例子
lua
Person = {
hp = 100
}
player = {}
setmetatable(player, { __index = Person })
print(player.hp) -- 100
🧠 发生了什么?
player.hp → player里没有
↓
去 __index 找
↓
Person.hp → 100
👉 一句话总结:
🔥 __index = "找不到就去这里拿"
🔥 四、用元表实现"类"
这才是重点👇
🎯 1. 定义一个类
lua
Player = {}
Player.__index = Player
🎯 2. 创建实例(构造函数)
lua
function Player:new(name, hp)
local obj = {
name = name,
hp = hp
}
setmetatable(obj, self)
return obj
end
🎯 3. 定义方法
lua
function Player:takeDamage(dmg)
self.hp = self.hp - dmg
end
🎯 4. 使用
lua
local p1 = Player:new("Hero", 100)
p1:takeDamage(20)
print(p1.hp) -- 80
🧠 五、这一套为什么成立?
关键在这句:
lua
setmetatable(obj, self)
等价于:
obj → 找不到字段
↓
Player(__index)
👉 所以:
🔥 方法其实都存在"类表"里,而不是实例里
🚀 六、实现继承(游戏开发必备)
🎯 例子:角色 → 战士
🧩 1. 父类
lua
Character = {}
Character.__index = Character
function Character:new(name, hp)
local obj = { name = name, hp = hp }
setmetatable(obj, self)
return obj
end
function Character:takeDamage(dmg)
self.hp = self.hp - dmg
end
🧩 2. 子类
lua
Warrior = {}
Warrior.__index = Warrior
setmetatable(Warrior, { __index = Character })
🧩 3. 扩展能力
lua
function Warrior:attack(target)
target:takeDamage(30)
end
🧩 4. 使用
lua
local w = Warrior:new("战士", 200)
local enemy = Character:new("怪物", 100)
w:attack(enemy)
print(enemy.hp) -- 70
👉 继承链:
实例 → Warrior → Character
⚠️ 七、新手最容易踩的坑
❗ 1. 忘记写 __index
lua
Player = {}
-- 忘了 Player.__index = Player
👉 结果:方法找不到 ❌
❗ 2. 用 . 而不是 :
lua
p1.takeDamage(10) -- ❌
p1:takeDamage(10) -- ✅
👉 因为:
: 会自动传 self
❗ 3. 继承写反
lua
setmetatable(Character, { __index = Warrior }) -- ❌
👉 会直接逻辑崩掉
🔥 八、实战:用OOP改造卡牌系统
(这一段非常关键,直接体现你"游戏开发深度")
🧩 1. 卡牌基类
lua
Card = {}
Card.__index = Card
function Card:new(id, name, cost)
local obj = {
id = id,
name = name,
cost = cost
}
setmetatable(obj, self)
return obj
end
🧩 2. 攻击卡
lua
AttackCard = {}
AttackCard.__index = AttackCard
setmetatable(AttackCard, { __index = Card })
function AttackCard:new(id, name, cost, damage)
local obj = Card.new(self, id, name, cost)
obj.damage = damage
return obj
end
function AttackCard:use(target)
target.hp = target.hp - self.damage
end
🧩 3. 治疗卡
lua
HealCard = {}
HealCard.__index = HealCard
setmetatable(HealCard, { __index = Card })
function HealCard:new(id, name, cost, heal)
local obj = Card.new(self, id, name, cost)
obj.heal = heal
return obj
end
function HealCard:use(player)
player.hp = player.hp + self.heal
end
👉 这就是:
🔥 一个可扩展的卡牌系统结构(商业项目级雏形)
🧠 九、高手总结(核心理解)
✅ 本质一句话:
👉 元表 = 控制Table行为的规则系统
✅ OOP本质:
实例 → 找不到 → 类表 → 再找不到 → 父类
✅ 游戏开发核心价值:
- ✔ 可扩展(加新卡不用改旧代码)
- ✔ 可维护(逻辑清晰)
- ✔ 数据 + 逻辑分离
📌 十、本篇总结
🔥 Lua没有类,但你可以用元表构建一个比类更灵活的系统。