第5章 元表与面向对象:行为外挂


文档摘要

第 5 章 · 元表与面向对象:行为外挂 章节摘要:元表是 Lua 把"行为如何定义"外挂出去的机制:表的索引失败、运算、比较、打印、垃圾回收,每种行为都有一个可改写的钩子位。宿主不改语言核心就能定制出默认值表、只读配置、继承链——这正是嵌入世界需要元表的原因。本章三节:5.1 讲元表与查找链的机制,5.2 盘点常用元方法,5.3 用"表加元表"造出类、继承与封装,回答"Lua 怎么做面向对象"。 学习目标 阅读完本章,你应当能够: 说清元表是什么(一张挂在表上的"后备行为表")、setmetatable 与 getmetatable 的用法、元表挂表不挂类型的规则; 画出 找不到时的完整查找链,区分 为表与为函数两种形态,掌握 rawget/rawset 绕过元方法的用法;

第 5 章 · 元表与面向对象:行为外挂

章节摘要:元表是 Lua 把"行为如何定义"外挂出去的机制:表的索引失败、运算、比较、打印、垃圾回收,每种行为都有一个可改写的钩子位。宿主不改语言核心就能定制出默认值表、只读配置、继承链——这正是嵌入世界需要元表的原因。本章三节:5.1 讲元表与查找链的机制,5.2 盘点常用元方法,5.3 用"表加元表"造出类、继承与封装,回答"Lua 怎么做面向对象"。

学习目标

阅读完本章,你应当能够:

  1. 说清元表是什么(一张挂在表上的"后备行为表")、setmetatable 与 getmetatable 的用法、元表挂表不挂类型的规则;
  2. 画出 t.k 找不到时的完整查找链,区分 __index 为表与为函数两种形态,掌握 rawget/rawset 绕过元方法的用法;
  3. 列出常用元方法的家族:索引对(index/newindex)、调用(call)、字符串化(tostring)、长度、等值与排序、算术与连接、回收与关闭;
  4. 用元表实现默认值表、只读表、运算符重载三类经典外挂;
  5. 用"表加元表加冒号语法"搭建类:构造器、方法、继承链、多继承、闭包式私有成员;
  6. 从寄宿视角解释:为什么"行为外挂"让宿主能在不动语言核心的前提下定制脚本层的语法行为。

核心概念速览

语言核心管"必然",元表管"或然":把可以商量的行为全部外包,核心就能保持小巧。

子章节导航

5.1 元表的概念与查找链

元表挂在哪里、什么时候被咨询、查找链怎么走——机制的三个问题。__index 的表形态给出委托与继承的原型,函数形态给出惰性计算与默认值的入口,raw 系列函数是调试与穿透的钥匙。本节是全章的地基。

5.2 常用元方法:从索引到运算符

按"读写、调用、呈现、比较、算术、生命周期"六组盘点元方法,每组配可运行的最小例子:默认值表与只读表(读写)、函数对象(调用)、自描述打印(呈现)、值语义比较(等值与次序)、向量运算(算术家族)、to-be-closed 与弱表(生命周期)。

5.3 用元表造对象:类与继承

把前两节的零件组装成面向对象:类即"共享一张元表的方法表",构造器即工厂函数,继承即 __index 链,多继承即函数形态的 __index 逐父查找,私有成员即闭包。末尾讨论"要不要用面向对象"的工程判断——Lua 社区半个流派只用表与函数,另一半写出完整 class 库,两种都合法。

子章节之间的逻辑关系

一句话论点:5.1 给机制、5.2 给零件、5.3 给组装——像先学电路、再认元件、最后装整机。

5.1 机制:元表挂表 · 查找链 · raw 穿透 │ ▼ 5.2 零件:六组元方法 · 每组最小例子 │ ▼ 组装 5.3 整机:类 · 继承 · 封装 · 取舍 │ ├──→ 第 6 章 模块即一张表 · 错误对象带元方法 └──→ 第 9 章 userdata 挂元表 · C 对象获得脚本行为

三个先修问题

元表挂在谁身上、什么时候被咨询? 挂在值(主要是表与 userdata)身上;只在"常规操作无答案"时咨询——键扑空问 index、写入落空问 newindex、陌生运算问算术族、转字符串问 tostring。常规路径命中时元表完全不参与,这就是 rawget 与普通访问的差别。

__index 的表形态与函数形态分别适合什么? 表形态是委托(继承链、配置回退、方法表),链式上溯成本低;函数形态是计算(默认值工厂、懒加载回填、多继承分发),灵活但每跳一次调用。同一条链里两种形态可以混用。

为什么面向对象不必内建? 因为类(共享元表的方法表)、继承(index 链)、封装(闭包或约定)都能用已有件组装——语言核心不为范式背书,范式以库的形式存在,团队按需取用或不用。

前置知识与后续延伸

  • 前置:第 3 章的表构造与引用语义(元表本身是表)、第 2 章的函数值与闭包(__index 函数形态、私有成员都要用)。
  • 为后续铺垫:模块的公共接口表与类同构(第 6 章);错误对象的 __tostring 让日志可读(第 6 章);userdata 配元表让 C 对象长得像本地值(第 9 章);字符串能直呼 string 库的方法,靠的正是字符串的默认元表(本章揭秘)。

本章心法

三句话带走本章:

**第一句:行为是外挂的。**语言核心只规定"常规路径",扑空、陌生运算、自我介绍这些"非常规时刻"交给元表——宿主不改语言就能定制行为,语言不背范式的锅。

第二句:读委托,写自立。__index 只在扑空时咨询、写在本体;继承、默认值、方法表全是这条规则的变奏。分清"自己的值"与"链上来的值",raw 系是验钞机。

**第三句:范式是选择不是信仰。**表加函数能解决的别上类,类能解决的别上继承链,三层链以上就该重新分层——Lua 把选择权全给你,也把选择的判断题全留给你。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U