Lua模块与元表(Metatable)

一、模块(module)

模块类似于一个封装库,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。
Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行。以下为创建自定义模块 module.lua

--文件名为module,lua
--定义一个modul的模块
module={}
--定义一个常量
module.var="Lian"

--局部函数,相当于C#中的私有函数,不能在外界调用
local function func1()
 print("这是一个局部私有函数")
end

--定义全局一个函数
function module.func2()
func1()
print("这是一个全局公有函数")
end

return module

由上可知,模块的结构就是一个 table 的结构,因此可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数。
上面的 func1 声明为程序块的局部变量,即表示一个私有函数,因此是不能从外部访问模块里的这个私有函数,必须通过模块里的公有函数来调用.

下面再去创建usermodule.lua文件去调用模块中的函数和变量,使用require 函数
Lua提供了一个名为require的函数用来加载模块。要加载一个模块,只需要简单地调用就可以了。

--require "模块名"
m= require "module"

print(m.var)--调用模块中的变量
m.func2()--调用模块中的全局函数

最后运行可以看到输出结果调用了module模块中的函数和变量

运行结果:
Lian
这是一个局部私有函数
这是一个全局公有函数
二、元表(Metatable)

在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作。
因此 Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关联了对应的元方法。
例如,使用元表我们可以定义Lua如何计算两个table的相加操作a+b。
有两个很重要的函数来处理元表:

setmetatable(table,metatable): 
对指定table设置元表(metatable),如果元表(metatable)中存在__metatable键值,setmetatable会失败 。

getmetatable(table): 返回对象的元表(metatable)。

如何对指定的表设置元表:

mytable={"Lua","Java","C","C#","C++"}--普通表
--使用__metatable可以保护元表,禁止用户访问元表中的成员或者修改
mymetatable={__metatable="lock"}--元表  元表扩展了普通表的行为

mytable=setmetatable(mytable,mymetatable)--给指定的表设定元表
print(getmetatable(mytable))--返回普通表的元表

输出结果:lock
__index 元方法
是 metatable 最常用的键。
当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。

如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。
__index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。

--__index用来处理访问到的索引不存在的时候怎么办
mytable={"Lua","Java","C","C#","C++"}--普通表
mymetatable={
  __index=function (tab,key)
      return "JavaScript"
   end
  }--元表  元表扩展了普通表的行为

mytable=setmetatable(mytable,mymetatable)--给指定的表设定元表
print(mytable[10])--访问表中不存在的键时会执行元表中的匿名函数

输出结果:JavaScript
__newindex 元方法
__newindex 元方法用来对表更新,__index则用来对表访问 。
当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。

--__newindex当我们对表的数据进行修改的时候,当我们给表添加新的键值对的时候会起作用
mytable={"Lua","Java","C","C#","C++"}--普通表
mymetatable={
  __newindex=function (tab,key,value)
      print("我们要修改的key为:"..key.."把这个key值修改为:"..value)

    rawset(tab,key,value)--设置键值对,添加输入进来的键值对
   end
  }--元表  元表扩展了普通表的行为
  mytable=setmetatable(mytable,mymetatable)--给指定的表设定元表
  mytable[6]="JavaScript"
  print(mytable[6])

输出结果:

我们要修改的key为:6把这个key值修改为:JavaScript
JavaScript

为表添加操作符
__add元方法:当两个表相加时实现相应的函数方法

mytable={"Lua","Java","C","C#","C++"}--普通表
mymetatable={
--两表相加将新表中的元素添加到mytable中去
  __add=function (tab,newtab)
     local mi=0
     for k,v in pairs(tab) do
        if (k>mi)then
            mi=k
        end
     end

     for k,v in pairs(newtab) do
        mi=mi+1
        table.insert(tab,mi,v)
     end
     return tab
   end
  }--元表  元表扩展了普通表的行为

  mytable=setmetatable(mytable,mymetatable)--给指定的表设定元表
  
  newtab={"PHP","Phthon"}
  
  --其中只要有一个表设置了元表都可以实现加法
  v=mytable+newtab

  
  for k,v in pairs(v) do
     print(k,v)
  end

输出结果:

1   Lua
2   Java
3   C
4   C#
5   C++
6   PHP
7   Phthon

其他操作符:

image.png

__call元方法
__call 元方法在 Lua 调用一个值时调用。也就是说当我们把表当作函数来使用的时候调用,例如:mytable(25)

mytable={"Lua","Java","C","C#","C++"}
 mymetatable={
 __call=function (tab,arg)
     print("Call元方法_"..arg)
 end
 }
  mytable=setmetatable(mytable,mymetatable)
 mytable("凉")

输出结果:Call元方法_凉
__tostring 元方法
__tostring 元方法用于修改表的输出行为。表示在使用输出print(table)的时候会调用元表中的函数,如下

mytable={"Lua","Java","C","C#","C++"}
 mymetatable={
 __tostring=function (tab)
      local str=""
      for k,v in pairs(tab) do
        str=str..v..","
      end
     return str
 end
 }
  mytable=setmetatable(mytable,mymetatable)

 print(mytable)

输出结果:

Lua,Java,C,C#,C++,
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容