在 Lua 中,使用“.”符号时容易出现 __index 和命名空间的混淆。
2014-12-19 4:7:2
收藏:0
阅读:108
评论:1
我对使用 "." 的以下两种语法感到困惑。
根据我的理解,
__index在键值不存在于表中但存在于其元表中时被调用。那么为什么列表表现为调用__index然后将本身分配给list.__index?list = {} list.__index = list setmetatable(list, { __call = function(_, ...) local t = setmetatable({length = 0}, list) for _, v in ipairs{...} do t:push(v) end return t end }) function list:push(t) if self.last then self.last._next = t t._prev = self.last self.last = t else self.first = t self.last = t end self.length = self.length + 1 end . . . local l = list({ 2 }, {3}, {4}, { 5 })Window.mt是否只是创建表格?为什么我们需要Window = {}作为一个命名空间?Window = {} -- create a namespace Window.mt = {} -- create a metatable Window.prototype = {x=0, y=0, width=100, height=100, } function Window.new (o) setmetatable(o, Window.mt) return o end Window.mt.__index = function (table, key) return Window.prototype[key] end w = Window.new{x=10, y=20} print(w.width) --> 100
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
所以为什么表列表表调用 __index 然后将自己赋给 list.__index?
在你的代码中,列表表从来没有调用过
__index。然而,赋值部分是 Lua 中一种常见的惯用法(也称为“hack”),可以节省一些内存。概念上涉及四种不同的表:列表对象(通过
{length=0}在你的代码中创建的表)包含
__index字段的元表,用于在尝试访问对象中不存在的字段时修改列表对象的行为list类,它包含所有列表对象的方法(如push方法),并且还用作列表对象的构造函数list类的元表(包含__call字段),使得你可以像调用函数一样调用list表由于元表字段始终以两个下划线 (
__) 开头,而正常方法通常不以此开头,因此你可以将元表字段和普通方法并排放置在单个表中而没有冲突。这就是这里发生的事情。list类表也用作列表对象的元表。因此,使用此技巧,你可以节省通常需要用于独立元表的内存(此表在标题栏中以方括号显示 Lua 5.2 在 x86-64 Linux 上的字节数):Window.mt 是否只是创建了一个表?
不是,
{}创建了一个表。但是,将这个新表保存在Window表的键 "mt" 下,可能是为了让这个Window"类" 的用户直接访问用于窗口对象的元表。仅根据你展示的代码,这不是绝对必要的,你可以使用本地变量代替。为什么我们需要 Window = {} 作为名称空间?
原则上,你可以分别存储
Window.mt、Window.new和Window.prototype,但如果你有多个类似Window的 "类",这样做会变得笨重。这样你就可以避免名称冲突,并且使用Window"类" 看起来更好看。另一个原因可能是
require只能从模块定义返回单个值,如果你想从模块中导出多个值(如new、mt和prototype),则需要一个表将它们包装在一起(或使用全局变量,但这被认为是不好的风格)。