在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
很快就要开始介绍Lua里的“面向对象”了,在此之前,我们先来了解一下Lua的模块。 1.编写一个简单的模块 Lua的模块是什么东西呢?通常我们可以理解为是一个table,这个table里有一些变量、一些函数… 等等,这不就是我们所熟悉的类吗? 没错,和类很像(实际上我说不出它们的区别)。 game = {} function game.play() print("那么,开始吧"); end function game.quit() print("你走吧,我保证你不会出事的,呵,呵呵"); end return game;
我们定义了一个table,并且给这个table加了两个字段,只不过这两个字段的值是函数而已。 至于如何使用模块,那就要用到我们之前介绍过的require了。 local function main() cc.FileUtils:getInstance():addSearchPath("src") game = require("game"); game.play(); end
注意,我们要require其他文件的时候,要把文件路径给设置好,否则会找不到文件。 [LUA-print] 那么,开始吧
2.为以后的自己偷懒——避免修改每个函数中的模块名 假设我们想把刚刚的game模块改个名字,改成eatDaddyGame,那么,我们需要做以下两件事情: 1).修改game.lua的文件名 如果批量修改,又怕有哪个地方改错。 于是,我们可以这么偷懒: game = {} local M = game; function M.play() print("那么,开始吧"); end function M.quit() print("你走吧,我保证你不会出事的,呵,呵呵"); end return M;
我们用一个局部变量M来代替了game,于是,以后我们只需要修改前面两个的game就可以了,函数部分的内容完全不需要去修改。 这个偷懒其实蛮有用的,某些情况下,修改越少,越安全~ 3.更进一步的偷懒——模块名参数 实际上,我们可以更加得偷懒,以后修改模块名,只需要修改模块的文件名就可以了,文件内容可以不管,具体怎么实现? 看代码: local M = {}; local modelName = ...; _G[modelName] = M; function M.play() print("那么,开始吧"); end function M.quit() print("你走吧,我保证你不会出事的,呵,呵呵"); end return M;
留意一下,这里有一个 local modelName = … 于是,当我们直接调用game的时候,其实就是在调用_G["game"]的内容了,而这个内容就是这里的M。 4.利用非全局环境制作更简洁和安全的模块 如果说,刚刚已经达到了我们作为高(ai)智(zhe)商(teng)人群的巅峰,那,你就太天真了。 巅峰就是要拿来超越的,还记得我们的非全局环境吗?就是那个setfenv函数。 local M = {}; local modelName = ...; _G[modelName] = M; setfenv(1, M); function play() print("那么,开始吧"); end function quit() print("你走吧,我保证你不会出事的,呵,呵呵"); end return M;
我们把game.lua这个模块里的全局环境设置为M,于是,我们直接定义函数的时候,不需要再带M前缀。 因为此时的全局环境就是M,不带前缀去定义变量,就是全局变量,这时的全局变量是保存在M里。 所以,实际上,play和quit函数仍然是在M这个table里。 另外,由于当前的全局环境是M,所以, 在这里不需要担心重新定义了已存在的函数名,因为外部的全局变量与这里无关了。 因为我们的全局环境改变了,所以print函数也找不到了。 为了解决这个问题,我们看看第5条内容吧~ 5.解决原全局变量的无法找到的问题——方案1 第一个方法,就是我们之前介绍过的,使用继承,如下代码: local M = {}; local modelName = ...; _G[modelName] = M; -- 方法1:使用继承 setmetatable(M, {__index = _G}); setfenv(1, M); function play() print("那么,开始吧"); end function quit() print("你走吧,我保证你不会出事的,呵,呵呵"); end return M;
没错,使用__index元方法就能解决这个问题了,当找不到print等函数时,就会去原来的_G里查找。 6.解决原全局变量的无法找到的问题——方案2 第二个方法更简单,使用一个局部变量把原来的_G保存起来,如下代码: local M = {}; local modelName = ...; _G[modelName] = M; -- 方法2:使用局部变量保存_G local _G = _G; setfenv(1, M); function play() _G.print("那么,开始吧"); end function quit() _G.print("你走吧,我保证你不会出事的,呵,呵呵"); end return M;
这种方法的缺点比较明显,那就是,每次调用print等函数时,都要使用_G前缀。 7.解决原全局变量的无法找到的问题——方案3 第三个方法比较繁琐,使用局部变量把需要用到的其他模块保存起来,如下代码: local M = {}; local modelName = ...; _G[modelName] = M; -- 方法3:保存需要使用到的模块 local print = print; setfenv(1, M); function play() print("那么,开始吧"); end function quit() print("你走吧,我保证你不会出事的,呵,呵呵"); end return M;
这种方法的缺点更明显了,所有用到的模块都要用局部变量声明一次,烦人。 8.你就笑吧,但,我还想更加偷懒——module函数 本以为刚刚介绍的那些技巧已经够偷懒的吧? local M = {}; local modelName = ...; _G[modelName] = M; setmetatable(M, {__index = _G}); setfenv(1, M);
就这几句代码,其实我们可以忽略不写,因为,我们有module函数,它的功能就相当于写了这些代码。 module(..., package.seeall); function play() print("那么,开始吧"); end function quit() print("你走吧,我保证你不会出事的,呵,呵呵"); end
注意,前面的几行代码都没了,只留下了一个module函数的调用。 module函数的调用已经相当于之前的那些代码了。 而package.seeall参数的作用就是让原来的_G依然生效,相当于调用了:setmetatable(M, {__index = _G});
在lua中,我们可以直接使用requeire(“model_name”)来载入别的文件,文件的后缀名是.lua,载入的时候直接执行那个文件了。 比如:my.lua 文件中 print(“hello world!”)
特别注意: 1、用require载入相同的文件时,只有第一次执行,以后都不执行。 2、如果你想让每次载入都执行文件,那么可以使用dofile(“my.lua”) 3、如果你想载入的时候不执行文件,等需要的时候再执行文件,那么可以使用loadfile(“my.lua”) local my=loadfile(“my.lua”)
... my()
|
请发表评论