Lua 学习笔记——metatable和__index

版权声明:本文为博主 Fisher1006 原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/fishe_r/article/details/77530369

最近学习lua今天突然对metatable和__index之间的关系有点不清楚,上网查了下加深了对metatable的理解,记录一下

还是用代码来解释,下面有图解,metatable和__index主要用于继承相关,有两种方式:

test.lua

local test = {}function test:new()self.__index = selfreturn setmetable({}, self)
endfunction test:say()print("111")
endlocal t1 = test:new()
t1.say()local t2 = t1:new()
t2.say()return test

test2.lua

local test2 = {}test2.__index = test2function test2:new()return setmetatable({}, self)    -- 这里的self 替换成 test2 试试
endfunction test2:say()print("222")
endlocal t3 = test2:new()
t3.say()local t4 = t3:new()
t4.say()            -- 这一步会报错return test2

上面的代码test.lua中t1,t2都能访问到new和say方法,但是test2中只有直接通过test2:new()生成的对象(t3)才能访问new和say方法,而通过test2:new()生成的子对象生成的对象(t4)则访问不到new和say方法

要解释上述问题,首先要知道lua从table中查找一个key时的流程,当从表t中查找k时:

  1. t中是否有k,有则返回,无则第2步
  2. t是否有metatable,无则返回nil,有则第3步
  3. t的metatable中是否有__index方法,无则返回nil,有则查找 __index对应的table或者方法

所以我们一步步分析test.lua中的代码:

local test = {}function test:new()...
endfunction test:say()...
end

这一句就是创建了一个table,我们用方块表示table则就是下面这样: 

接下来实例化一个对象:

local t1 = test:new()

这里调用test:new(),相当于test.new(test),函数中的self为test,所以这一步改变了test表,结果用图表示为: 

图中椭圆表示__index函数,__index指向test自身,可以看到这时test表和上面不一样,而t1是一个新生成的表,这个表的metable为test,但是t1本身没有其他内容

再来看最后一步

local t2 = t1:new()

此时结果为: 

这一步new函数中的的self为t1,所以最后改变了t1的__index指向t1,生成新的表t2的metatable为t1,由于t1和t2都有metatable并且metatable中都有__index方法所以都可以访问test中的new和say方法,即使它们自身没有这两个方法

再来看test2.lua中有什么不同,同理按照上面的分析有三个图,就不一一解释了 

唯一不同的地方就在于__index方法的设置,在test2.lua中 __index只在test2表中设置,在继承过程中,并没有设置对应的__index方法,所以t3可以访问到new和say,但是t4则不可以

不过由此引出我一个问题,我们可以看到lua中查找不存在的k时,最终起作用的其实是__index方法,类似的还有操作符元方法等,但是却要先找metatable,然后找metatable里面的这些元方法,metatable在这里是相当于一个代理一样的作用,那么为什么不能直接在自身的表中设置,为什么要有metatable这个中间表??

猜想一:可能是模块化的考虑也就是把这些元方法集中在一起

  • 但是lua中有一个常用的用法就是 __index指向自身,上述例子就是这样,那么这个table里面本身就有元方法和自己的数据,而lua也没有说不推荐这么做,所以也不符合模块化的考虑

猜想二:可能是为了多个table方便共享同一个metatable

  • 问题是直接在自身table中设置__index指向同一个metatable也可以达到这种效果

猜想三:刚刚想到如果没有metatable的话,直接用__index指向要设置的元表,那么如果我想把自身作为基类,用__index指向自身,就会陷入死循环

  • 不知道是不是因为这点才引入了metatable这么一个中间代理

所以不清楚这部分的设计理念是什么,如果有知道的可以留言下

理解lua中的metatable和__index相关推荐

  1. Lua中的metatable

    Lua中的metatable Lua 中每个 值value(或者对象)都可以有一个 metatable(在 Lua 5.0 只有table和 userdata能够存在 metatable).每个 ta ...

  2. 两个函数彻底理解Lua中的闭包

    本文通过两个函数彻底搞懂Lua中的闭包,相信看完这两个函数,应该能理解什么是Lua闭包.废话不多说,上 code: 1 --[[************************************ ...

  3. 理解lua中 . : self

    文章目录[点击展开](?)[+] 前言 点号定义和调用 冒号定义和冒号调用 运行结果 相互调用 相互调用运行结果 总结 前言 在LUA中,经常可以看到:. self,今天在CSDN上看到一篇博客写的很 ...

  4. 关于lua中userdata的理解

    @[TOC] 关于lua中userdata的理解 关于Userdata的理解 Userdata数据结构 userdata是用来存放用户自定义数据结构的实列,userdata的类型有两种类型,分别是li ...

  5. 对Lua中Userdata的理解

    目录 一.概述 二.源码实现 相关函数实现 1,lua_pushlightuserdata 2,lua_newuserdata 3,luaC_newobj(lgc.c) 4,createstrobj( ...

  6. lua的元表metatable及元方法

    前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了"+"符号,就可以进行类的加法运算.在Lu ...

  7. Lua元表(Metatable)简易教程

    文章目录 0.友情链接 1.引言 2.创建一个元表 2.1.__tostring方法 2.2.__add和__mul方法 2.3.__index方法 2.4.__call方法 3.完整代码 0.友情链 ...

  8. Lua中的面向对象实现探讨

    Lua中,面向对向是用元表这种机制来实现的.元表是个很"道家"的机制,很深遂,很强大,里面有一些基本概念比较难理解透彻.不过,只有完全理解了元表,才能对Lua的面向对象使用自如,才 ...

  9. XLua源码学习:Lua中调用CS

    在使用lua代码开发的过程中,一个非常重要的部分是对C#代码的调用,接下来就结合源码分析理解它的实现: 在lua中,使用诸如以下代码便可以调用C#的代码: CS.UnityEngine.Debug.L ...

最新文章

  1. 【linux】Valgrind工具集详解(十三):Helgrind(线程错误检测器)
  2. vue 报错 Cannot read property ‘__ob__‘ of undefined的解决方法
  3. java子类参数传递给父类_java – 为什么调用将父类作为参数的方法调用,而不是将子类作为参数获取的方法?...
  4. python两个数相加时_两数相加 leetcode Python
  5. .NET MAUI 预览版 6 发布
  6. CC++中的qsort库函数
  7. opencv基础---直方图均衡化(原理equalizeHist)
  8. 谈谈写程序与学英语 --宋劲杉
  9. 用Delphi编写的一个上网助手
  10. Linux学习-菜鸟教程知识(一)
  11. wps画 ui 原型图
  12. 常见泰勒展开公式及复杂泰勒展开求法
  13. 设计模式——工厂方法模式
  14. java中cleanup的使用_java – google guava缓存invalidateAll()和cleanUp()之间的区别
  15. 【转载】GGB0/OB28/OKC7/GGB1/OBBH/OKC9 FICO增强
  16. CTF也需要了解点电脑系统还原点
  17. opc服务器连接plc断开显示,如何判断OPC与PLC通讯失败
  18. 用 MAUI 在Windows 和 Linux 绘制 PPT 图表
  19. 如何按ASCII码比较_Pt100铂热电阻信号如何采集转换?
  20. Jetson Xavier NX相关安装

热门文章

  1. 山东科技职业学院单招计算机,山东科技职业学院单招
  2. mybatis jar包_Spring4+SpringMVC+MyBatis整合思路
  3. Eigen教程(5)之块操作
  4. 存储可向外扩展无线传输
  5. DHCP配置 TFTP服务
  6. java语言函数存储在哪个包_java专项联系题
  7. 页面前端的水有多深?再议页面开发
  8. 不是程序员,代码也不能太丑!python官方书写规范:任何人都该了解的 pep8
  9. 【转载】Android 工具-adb原理
  10. 【JAVA基础知识总结】JAVA对象转型之上转型对象与下转型对象