1、表

    表(table)是Lua语言中非常独特的地方;

    Lua中的表即支持数组风格的实现(顺序表),也支持key-value风格的实现(哈希表),并且这两种方式还能混用(即使不推荐);

    表中可以存放任何数据类型;

    Lua有一个很重要的特性:函数是一级类型,也就是说,表中存放的类型也包括函数;

    (补充:单纯利用表,就已经可以实现一个简单的类了)

需要注意的地方:

    需要注意,不同于大多数编程语言,Lua数组风格的表,元素的下标是从 1 开始的;

    需要注意,当需要删除表中的元素时,正确的做法是调用table.remove()函数,而不是直接将value置为nil;

    需要注意,表中的变量和函数,都是不能用local关键词进行修饰的

2、元表

    元表(metatale),可以看作是表的一种扩展,缺省情况下我们创建的表是没有元表的

setmetatable(table, metatable)

可以通过上述方法为指定的表设置对应的元表,元表和表的大致关系如下图:

    接下来介绍2个有关元表的函数:

setmetatable(table, metatable);   -- 将 metatable 设置成 table 的元表getmetatable(table)          -- 将返回 table 的元表

    具体的使用:

local table = { 1, 2, 3 }           -- 表      local metatable = { __add = myAdd }            -- 元表

    上面这段代码的作用是: 将 metatable 设置成 table 的元表

其中在元表 metatable 实现了 + 操作符 的重载,有关表的函数重载,接下来会介绍

3、重载

    从上面的图片可以看到, 元表metatable中有若干的key,其中每个key代表一个方法

当我们用自己实现的函数作为value 填充 这个表格,就实现了类似C++ 的重载

支持重载的方法及对应的key如下:

__add(a, b) --加法__sub(a, b) --减法__mul(a, b) --乘法__div(a, b) --除法__mod(a, b) --取模__pow(a, b) --乘幂__unm(a) --相反数__concat(a, b) --连接__len(a) --长度__eq(a, b) --相等__lt(a, b) --小于__le(a, b) --小于等于__index(a, b) --索引查询__newindex(a, b, c) --索引更新__call(a, ...) --执行方法调用__tostring(a) --字符串输出__metatable --保护元表

    接下来分别演示两个比较有代表性的方法的重载: __add() 和 __index():

__add():

     “+”操作符的重载可以实现两个功能:取并集,或者 每个元素相加,这里 实现取并集的功能

所以首先需要实现一个取并集的函数 myAdd(self, val) 其中两个形参,分别传 "+ " 左边的变量 self(关键字) 和 右边的变量 tbRight

local function myAdd(self, tbRight)	local tmp = {}    -- 临时表	local tbResult = {}    -- 存放最终的并集	-- 哈希处理	for k, v in pairs(self) do		tmp[v] = 1	end	for k, v in pairs(tbRight) do		tmp[v] = 1	end	-- 加入到 tbResult(哈希映射)	local count = 1	for k, v in pairs(tmp) do		table.insert(tbResult, k)	end	return tbResultend

    接下来 创建一个表 tb, 给 tb 设置元表 metatb,并将 metatb 的 __index 字段 赋值为 myAdd方法,实现重载:

local tb1 = {10, 20, 30}local metatb = {__add = myAdd}setmetatable(tb1, metatb)-- tb1 和 tb2 取并集local tb2 = {20, 30, 50}local rettb = tb1 + tb2

②__index() 

    __index()字段 重载的函数,描述了通过进行key访问某个table 的方式,包括: "." 以及 "[]" 

    当然,table 本身是可以通过key进行元素的访问的,

而重载的作用就在于,当我们对指定table的key进行访问,并且这个key 在 table 本身不存在时,才会调用 __index()函数,从而对表进行扩展

    这是一个非常重要的重载,正是因为能实现__index()的重载,我们才能用Lua实现一系列比较高级的特性

    要实现这个工作,我们依然需要以下步骤:

    1、实现一个函数myIndex,

    2、将metatable的__index字段设置成myIndex, 

    3、调用setmetatable方法:

local function myIndex(self, key)	local TbAddition = {d = 4, e = 5}	return TbAddition[key]endlocal tb = {a = 1, b = 2, c = 3}-- 没有在上文单独定义metatable,而是直接作参数setmetatable(tb, {__index = myIndex})

    这样设置完以后,访问 tb["d"] 、 tb["e"],或者 tb.d、tb.e 由于tb本身没有这两个key,因此程序会调用 myIndex方法,并返回正确的结果

补充:

一些语法糖:

1、. [] 传入的参数

"." 是一种语法糖,当key为非数字类型,比如说 "d"时, tb["d"] 和 tb.d 这两种方式是等价的,因此在重载__index时,并不用额外关心这两种情况

2、直接将扩展的表赋值给 __index 字段

如下:

setmetatable(tb, {__index = {d = 4, e = 5} } )

这种方式没有手动定义 __index的方法,但仍然能实现重载

4、实现面向对象

正文4

5、闭包

5、实现继承

正文5

6、实现私有属性的保护

正文6