Lua中metatable和__index的联系
Lua中metatable和__index的联系
可以参考 http://blog.csdn.net/xenyinzen/article/details/3536708
来源 http://blog.csdn.net/fishe_r/article/details/77530369
最近学习lua今天突然对metatable和__index之间的关系有点不清楚,上网查了下加深了对metatable的理解,记录一下
还是用代码来解释,下面有图解,metatable和__index主要用于继承相关,有两种方式:
test.lua
local test = {}
function test:new()
self.__index = self
return setmetable({}, self)
end
function test:say()
print("111")
end
local t1 = test:new()
t1.say()
local t2 = t1:new()
t2.say()
return test
test2.lua
local test2 = {}
test2.__index = test2
function test2:new()
return setmetatable({}, self) -- 这里的self 替换成 test2 试试
end
function test2:say()
print("222")
end
local 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时:
- t中是否有k,有则返回,无则第2步
- t是否有metatable,无则返回nil,有则第3步
- t的metatable中是否有__index方法,无则返回nil,有则查找 __index对应的table或者方法
所以我们一步步分析test.lua中的代码:
local test = {}
function test:new()
...
end
function 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的联系的更多相关文章
- Lua中的metatable详解
转自:http://www.jb51.net/article/56690.htm Lua 中 metatable 是一个普通的 table,但其主要有以下几个功能: 1.定义算术操作符和关系操作符的行 ...
- lua学习:lua中“类”的实现
在之前的面试遇到考用lua实现类的题目.现在就补补这块知识点. 我们都知道Lua中的table是一个对象.拥有状态,拥有self,拥有独立于创建者和创建地的生命周期. 一个类就是一个创建对象的模具.L ...
- lua 14 metatable (类似操作符重载)
转自:http://www.runoob.com/lua/lua-metatables.html 感性认识: “Lua中Metatable这个概念, 国内将他翻译为元表. 元表为重定义Lua中任意一个 ...
- 【Lua】Lua中__index与元表(转)
转载于:http://blog.csdn.net/xocoder/article/details/9028347 Lua的表本质其实是个类似HashMap的东西,其元素是很多的Key-Value对,如 ...
- lua中的metatable和metamethod
--元表和元方法给lua里的值设定一些操作,让我们可以对这些操作自定义 --创建一个新的table变量时,它是不存在元表的 --在Lua中,只能设置table的元表,其他类型的值的元表,只能通过C代码 ...
- Lua中的元表(metatable)、元方法(metamethod)详解
在第一次看见这两样东西的时候,可能会觉得它很深奥,但其实很好理解,虽然实际上它可能真的很深奥.(小若:停!滚粗.) 1.知道为什么1 + 1 = 2吗? 为什么在Lua中,1+1会等于2呢?(小若:难 ...
- lua元表Metatable
Lua 中的每个值都可以用一个 metatable. 这个 metatable 就是一个原始的 Lua table , 它用来定义原始值在特定操作下的行为. 你可以通过在 metatable 中的特定 ...
- lua 中的面向对象
lua 是一种脚步语言,语言本身并不具备面向对象的特性. 但是我们依然可以利用语言的特性,模拟出面向对象的特性. 面向对象的特性通常会具备:封装,继承,多态的特性,如何在lua中实现这些特性,最主要的 ...
- Lua中的weak表——weak table
弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...
随机推荐
- angular学习笔记01
angular.js路由功能 用于实现单页应用 //html 代码 <div ng-view></div> //js代码 angular.module('myM1',['ng' ...
- pmap 命令详解
通过查看帮助,返回了如下信息: Usage: pmap [options] pid [pid ...] Options: -x, --extended show detai ...
- Spring 学习——基于Spring WebSocket 和STOMP实现简单的聊天功能
本篇主要讲解如何使用Spring websocket 和STOMP搭建一个简单的聊天功能项目,里面使用到的技术,如websocket和STOMP等会简单介绍,不会太深,如果对相关介绍不是很了解的,请自 ...
- LeetCode-2 Keys Keyboard
package Classify.DP.Medium; import org.junit.jupiter.api.Test; /** Initially on a notepad only one c ...
- eslint使用
参考文档 http://www.cnblogs.com/hahazexia/p/6393212.html http://blog.guowenfh.com/2016/08/07/ESLint-Rule ...
- MVC使用jQuery从视图向控制器传递Model,数据验证,MVC HTML辅助方法小结
//MVC HTML辅助类常用方法记录 (1)@Html.DisplayNameFor(model => model.Title)是显示列名, (2)@Html.DisplayFor(model ...
- TreeViewItem实现整行选中 (两种用法)
用法一 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quo ...
- Charle抓包与wireshark使用
今天就来看一下Mac上如何进行抓包,之前有一篇文章介绍了使用Fidder进行抓包 http://blog.csdn.net/jiangwei0910410003/article/details/198 ...
- win10 uwp 获取指定的文件 AQS
很多时候不需要获取整个文件夹的文件,是需要获取文件夹里指定的文件. 那么 UWP 如何对文件夹里的文件进行过滤,只拿出自己需要的文件? 本文:如何使用通配符或文件匹配方式在uwp获取文件夹中指定的文件 ...
- WPF 绑定密码
我们发现我们无法绑定密码框的密码,PasswordBox 的 Password 不能绑定. 我们想做 MVVM ,我们需要绑定密码,不能使用前台 xaml.cs 监听 密码改变得到密码的值,传到 Vi ...