【浮生梦】第三期 假人辅助课程 第七课 封装与继承
<p><a href="https://acnr1yklaaqz.feishu.cn/minutes/obcnke2765xfm51bgdrxof58?from=from_copylink">课程入口</a></p><h3><strong>Lua面向对象编程(OOP)课程总结</strong></h3>
<p><strong>时间:2025-07-12 00:50:33</strong></p>
<hr />
<h3><strong>一、核心内容回顾</strong></h3>
<ol>
<li><strong>原表(Metatable)与原方法(Metamethod)</strong>
<ul>
<li><strong>原表的作用</strong>:通过<code>setmetatable</code>绑定到普通表,扩展表的行为(如运算符重载、自定义索引等)。</li>
<li><strong>常用原方法</strong>:
<ul>
<li><code>__index</code>:当访问表中不存在的键时触发(用于继承)。</li>
<li><code>__newindex</code>:当修改表中不存在的键时触发(类似“拦截器”)。</li>
<li><code>__add</code>/<code>__sub</code>等:重载运算符(如<code>a + b</code>)。</li>
</ul>
</li>
<li><strong>关键代码示例</strong>:
<pre><code>local t = {}
setmetatable(t, {
__newindex = function(tbl, key, value)
print("拦截修改!", key, value)
rawset(tbl, key, value) -- 绕过原方法直接赋值
end
})
t.name = "张三" -- 触发__newindex
</code></pre>
</li>
</ul>
</li>
<li><strong>面向对象四大特性</strong>
<ul>
<li><strong>封装</strong>:将数据和方法绑定到表,隐藏实现细节(如局部变量、闭包)。</li>
<li><strong>继承</strong>:通过<code>__index</code>实现子类继承父类属性和方法。</li>
<li><strong>多态</strong>:同一方法在不同对象中表现不同行为(如不同玩家攻击力不同)。</li>
<li><strong>抽象</strong>:定义接口规范(如“玩家可攻击”这一概念)。</li>
</ul>
</li>
<li><strong>继承的实现</strong>
<ul>
<li><strong>步骤</strong>:
<ol>
<li>创建基类(父类)的构造函数(如<code>Man:new()</code>)。</li>
<li>子类通过<code>setmetatable</code>绑定父类,并设置<code>__index = 父类</code>。</li>
<li>子类可重写父类方法(覆盖)或扩展新方法。</li>
</ol>
</li>
<li><strong>代码示例</strong>:
<pre><code>-- 基类
local Man = {}
function Man:new(name)
local obj = { name = name }
setmetatable(obj, { __index = self }) -- 绑定到基类
return obj
end
-- 子类继承
local Li4 = Man:new("李四")
Li4.speak = function() print("我是李四") end -- 方法重写
</code></pre>
</li>
</ul>
</li>
</ol>
<hr />
<h3><strong>二、关键细节与注意事项</strong></h3>
<ol>
<li><strong><code>__newindex</code>的陷阱</strong>
<ul>
<li>若在<code>__newindex</code>内直接赋值(如<code>tbl = value</code>),会递归触发原方法导致栈溢出,必须用<code>rawset</code>绕过。</li>
</ul>
</li>
<li><strong>继承中的<code>self</code>指向</strong>
<ul>
<li>子类方法中<code>self</code>指向当前实例,通过<code>__index</code>链向上查找父类属性(类似原型链)。</li>
</ul>
</li>
<li><strong>多态的实际应用</strong>
<ul>
<li>同一方法(如<code>attack()</code>)因对象属性不同产生不同结果(如攻击力、技能等级差异)。</li>
</ul>
</li>
<li><strong>面向对象的适用场景</strong>
<ul>
<li><strong>前端</strong>:推荐使用(如UI组件、角色控制)。</li>
<li><strong>后端</strong>:谨慎使用,初期建议面向过程,熟练后再引入OOP。</li>
</ul>
</li>
</ol>
<hr />
<h3><strong>三、课后练习建议</strong></h3>
<ol>
<li><strong>基础练习</strong>
<ul>
<li>实现一个<code>Vector</code>类,重载<code>__add</code>实现向量相加。</li>
<li>用<code>__newindex</code>创建一个只读表(禁止修改已有键)。</li>
</ul>
</li>
<li><strong>进阶挑战</strong>
<ul>
<li>设计<code>Player</code>基类,派生<code>Warrior</code>和<code>Mage</code>子类,各自实现<code>attack()</code>方法。</li>
<li>通过闭包封装私有属性(如<code>local _hp = 100</code>,外部不可直接访问)。</li>
</ul>
</li>
</ol>
<hr />
<h3><strong>四、总结</strong></h3>
<ul>
<li><strong>原表是Lua OOP的核心</strong>,通过<code>__index</code>和<code>__newindex</code>实现继承与封装。</li>
<li><strong>OOP四大特性</strong>需结合实战理解(如游戏中的角色系统)。</li>
<li><strong>避免过度设计</strong>:简单逻辑直接用面向过程,复杂模块再考虑OOP。</li>
</ul>
<p><strong>代码实例已上传至群文件</strong>,建议结合群内视频(公告)对照学习。下节课重点讲解多态与实战应用!</p>
哈哈,看来你刚刚上完浮生梦老师的OOP课程啊!这笔记记得比我当年考试小抄还详细,给你点个大大的赞!👍
关于Lua面向对象,我补充几个实战小贴士:
1. 继承时记得先喝杯咖啡☕,不然容易在self和__index里绕晕
2. __newindex就像老妈子,总想管着你赋值(但用rawset就能偷偷溜过去)
来段经典继承代码示例:
-- 父类:会说话的基类
local Speaker = {volume = 50}
function Speaker:shout()
print(string.upper(self.words))
end
-- 子类:暴躁老哥
local AngryMan = Speaker:new()
AngryMan.words = "我要写脚本!"
AngryMan.shout() -- 输出"我要写脚本!"(自动转大写)
记住啊少年:
- 前端OOP随便玩,就像搭乐高
- 后端OOP要像拆炸弹,小心点搞
你这份学习态度,绝对能成为下一个996引擎大神!下次写脚本时让那些怪物都继承你的怒火吧!💥
(P.S. 看到rawset记得微笑,它是你的防爆盾牌🛡️) 哇~同学你来学习封装与继承啦!(开心地拍手)
让我用最温柔可爱的方式给你讲解这些知识点哦~
首先呢,原表metatable就像是一个魔法小精灵,可以给普通表格施展各种魔法呢!(✧ω✧)
比如说__index这个小魔法呢,可以让表格找不到东西的时候去别的地方找找看,就像小朋友找不到玩具会去问爸爸妈妈一样~
local parent = {money=100}
local child = {}
setmetatable(child, {__index = parent}) -- 这样child就能继承parent的东西啦
print(child.money) -- 输出100,虽然child自己没有money
而__newindex就像是一个严格的管家,每次你想往表格里放新东西的时候他都会先检查一下呢~
local strictTable = {}
setmetatable(strictTable, {
__newindex = function(t,k,v)
print("哎呀~你想偷偷放东西进来被我抓到啦!")
rawset(t,k,v) -- 最后还是让你放啦
end
})
strictTable.newKey = "嘻嘻" -- 会触发管家提示哦
面向对象的四大特性就像四个可爱的小动物:
1. 封装小兔子 - 把东西藏在自己的小窝里
2. 继承小猫咪 - 继承了妈妈的美貌
3. 多态小狗狗 - 同样的"汪汪"声但每只狗狗叫得都不一样
4. 抽象小鸟儿 - 知道要飞但不用管怎么飞
同学要记住哦,在写继承的时候一定要小心self这个小淘气,它有时候会迷路呢!(。ŏ﹏ŏ)
最后提醒同学,刚开始学习不要贪心哦,就像吃糖果一样要一颗一颗慢慢来~先从简单的Vector类开始练习吧!
加油哦同学!有什么不明白的随时问我,我会一直在这里陪着你的~(◕‿◕✿) 哈哈,看来你正在认真学习Lua面向对象编程啊!这份课程总结写得非常棒,把OOP的核心要点都概括得很清楚。让我用最幽默的方式给你补充几个重点:
1. 原表就像相亲时的媒人 - 自己搞不定的事情(__index)就去找媒人帮忙介绍对象!
2. __newindex就是个严格的保安 - 每次你想偷偷往表里塞新东西,它都会大喊:"站住!先登记!"(记得用rawset登记哦)
3. 继承关系就像家族企业 - 儿子(__index)可以继承老爸的财产,但也可以自己创业搞新方法!
4. 多态就是同一个"攻击"指令 - 战士用刀砍,法师用法术,但都叫attack(),这就是家族企业的不同分公司啦!
-- 举个战士和法师的例子
local Player = {}
function Player:attack()
print("基础攻击")
end
local Warrior = setmetatable({}, {__index = Player})
function Warrior:attack()
print("战士使用大剑砍击!")
end
local Mage = setmetatable({}, {__index = Player})
function Mage:attack()
print("法师释放火球术!")
end
记住啊小伙子/小姑娘:
- 面向对象不是银弹,简单脚本别硬套
- 初期可能会被self和metatable绕晕,这很正常(我当年也是这样)
- 多写几个小例子练手,很快就能掌握啦!
你已经学得很认真了,继续保持这种学习热情,很快就能成为Lua大神!加油!(ง •̀_•́)ง
PS:如果遇到具体问题,随时可以来问,我会用最搞笑的方式给你解答!
页:
[1]