近日开始频繁使用Lua,于是把这块东西理了一下,特此记录。
Lua的表本质其实是个类似HashMap的东西,其元素是很多的Key-Value对,如果尝试访问了一个表中并不存在的元素时,就会触发Lua的一套查找机制,也是凭借这个机制来模拟了类似“类”的行为
举例说明:
tempTable = {}
print(tempTable.memberA) --这里试图打印tempTable并不存在的成员memberA
执行结果:nil
输出为nil的原因很简单,tempTable中并没有memberA这个成员,这符合我们平时对HashMap的认知。但对于Lua表,如果tempTable有元表,情况就不同了。
什么是元表:
元表像是一个“操作指南”,里面包含了一系列操作的解决方案,例如__index方法就是定义了这个表在索引失败的情况下该怎么办。
__index元方法:
按照之前的说法,如果A的元表是B,那么如果访问了一个A中不存在的成员,就会访问查找B中有没有这个成员。这个过程大体是这样,但却不完全是这样,实际上,即使将A的元表设置为B,而且B中也确实有这个成员,返回结果仍然会是nil,原因就是B的__index元方法没有赋值。别忘了我们之前说过的:“元表是一个操作指南”,定义了元表,只是有了操作指南,但不应该在操作指南里面去查找元素,而__index方法则是“操作指南”的“索引失败时该怎么办”。这么说有点绕。所以:
举个栗子:)
father = {
house=1
}
son = {
car=1
}
setmetatable(son, father) --把son的metatable设置为father
print(son.house)
输出的结果是nil,但如果把代码改为
father = {
house=1
}
father.__index = father -- 把father的__index方法指向自己
son = {
car=1
}
setmetatable(son, father)
print(son.house)
输出的结果为1,符合预期
这样一来,结合上例,来解释__index元方法的含义:
在上述例子中,访问son.house时,son中没有house这个成员,但Lua接着发现son有元表father,注意:此时,Lua并不是直接在father中找名为house的成员,而是调用father的__index方法,如果__index方法为nil,则返回nil,如果是一个表(上例中father的__index方法等于自己,就是这种情况),那么就到__index方法所指的这个表中查找名为house的成员,于是,最终找到了house成员。
注:__index方法除了可以是一个表,还可以是一个函数,如果是一个函数,__index方法被调用时将返回该函数的返回值。
到这里,总结一下Lua查找一个表元素时的规则,其实就是如下3个步骤:
1.在表中查找,如果找到,返回该元素,找不到则继续
2.判断该表是否有元表(操作指南),如果没有元表,返回nil,有元表则继续
3.判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值
分享到:
相关推荐
元表可以通过`setmetatable`函数设置给一个表,其中包含了各种元方法,如`__index`、`__newindex`、`__tostring`等。元方法定义了表如何响应某些操作。 例如,可以通过设置`__index`元方法来自定义当访问不存在的键...
3. **元表与元方法**:Lua中的元表是实现面向对象编程的基础,它们在`ltable.c`中被处理。元方法通过`__index`和`__newindex`等元字段实现,提供了一种灵活的动态行为。 4. **垃圾收集**:Lua的垃圾收集机制在`lgc....
当尝试对一个对象执行乘法操作时,Lua会查找该对象的元表,如果找到了__mul元方法,就会调用它来执行自定义的乘法逻辑。这使得我们可以为自定义数据类型赋予丰富的操作符行为。 最后,我们来谈谈weak表。在Lua中,...
- 如果 `__index` 是一个表,Lua将在该表中查找相应的键。 - 如果 `__index` 是一个函数,Lua将调用该函数,并将原表和键作为参数传递给函数。 这种机制使得Lua能够实现非常灵活的数据结构和行为定制,例如创建具有...
- **查找元素**:可以使用 `for` 循环或 `pairs` 迭代器查找元素,也可以用 `table.find(list, value)` 自定义函数实现查找功能。 - **排序列表**:由于Lua的列表可以包含任意类型的元素,排序需要自定义比较函数...
- **实现**:通过元表的`__index`元方法实现继承。 ##### 16.3 多重继承 - **定义**:一个类可以继承多个父类的特性。 - **挑战**:解决命名冲突等问题。 ##### 16.4 私有性 - **定义**:限制类内部数据的访问权限...
Lua是一种轻量级的脚本语言,主要用于嵌入到其他应用程序中作为扩展。...理解这些细节有助于深入掌握Lua的内部工作原理,从而更好地利用Lua进行编程。在编写Lua扩展模块或者进行性能优化时,了解这些底层机制尤其重要。
请注意, (如果你对性能有很高的需求)把你的函数放到表里面将增加查找函数的时间. 7 绑定函数到Lua 为了绑定函数到Lua,你可以使用函数 luabind::def(). 它的声明如下: template, class policies> void def(const ...
该函数首先查找或创建指定索引处的表,然后将字段名和值关联起来存储在表中。这一操作是Lua中动态数据结构管理的核心之一。 ### 2. Lua对象 (lobject.h) #### 2.1 Value 在Lua中,`Value` 是所有数据类型的基类,它...
`table.concat(t, separator)`可以将table中的元素连接成一个字符串,`table.insert(t, value)`向表末尾插入元素,`table.remove(t, index)`移除并返回表中指定索引的元素。`table.foreach(t, function)`可以遍历...
- **查找**:`indexOf()`和`lastIndexOf()`用于查找元素的索引,`contains()`判断数组是否包含某个元素。 - **拷贝**:`clone()`函数创建数组的副本,避免原始数组被修改。 - **转换**:`toArray()`可能将其他...
使用大量C 14特性Variadic Template 和 index_sequence, SFINAE enable_if 和 type_traits, tuple, function, forward_ref, decltype(auto)。通过vc2015,gcc5.0,clang3.6编译new feature 新特性一览:导入lua的函数...
1. **元表(metatable)**:Lua允许为每个表格设置元表,元表包含了控制表格行为的元方法。例如,通过设置`__add`元方法,可以实现表格的加法操作。 2. **元方法**:如`__index`元方法可以指定当尝试访问不存在的键...
7. **getmetatable(obj, mtable)**:获取对象的元表,元表在Lua中用于实现对象的行为和属性。 8. **loadstring("Lua code")**:解析字符串中的Lua代码并返回一个函数,可以将这段代码在之后的时刻执行。 9. **next...
网页到底是什么? ...HTML是一种标记语言,它使用各种标签来定义文本、图像、链接等元素的结构和样式。... ...<!...在实际开发中,还需要结合具体的硬件平台和编程语言,如C#、Lua等,进行程序设计和调试。
本实践详解将深入探讨Redis中的核心命令及其在实际应用中的使用方法。 首先,我们来了解一下Redis的基本数据类型:字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。这些数据...
- **Lua 脚本 (EVAL/EVALSHA)**: 允许用户编写 Lua 脚本来执行复杂的操作,提高性能并减少网络延迟。 - **持久化 (SAVE/BGSAVE/RDB/AOF)**: 提供了多种方式来保存数据到磁盘,以防止数据丢失。 - **复制 (SLAVEOF)**...
`LINDEX key index`:返回列表键`key`中指定索引`index`上的元素。 ##### 2.4.11 llen `LLEN key`:返回列表键`key`的长度。 **2.5 Sets类型及操作** 集合(Set)是一个无序的、不重复的字符串集合。 ##### ...