Lua全局环境
定义一个全局变量
gName ="我是全局变量";
用三种方式输出变量的值
print(gName);
print(_G["gName");
print(_G.gName);
2.保留原来的_G
-- gNane="我是全局变量"
只要在定义新的环境时,把_G作为一个字段放到新的table里,就可以调用原来的全局变量了。
-- setfenv(1,{g=_G})
-- g.print(gNane)
-- gNane="我是全局变量2"
-- g.print(gNane)
-- g.print(g.gNane)
运行结果:nil
我是全局变量2
我是全局变量
setfenv函数两个参数分别代表:
1).第一个参数可以是即将要改变环境的函数,也可以是一个数字。数字1代表当前函数,数字2代表调用当前函数的函数,后面以此类推。
2).第二个参数,新的全局环境table。
3.使用_index保留原来的_G
定义一个全局变量
gName: “我 是 老 变 量“ ;
-一一个table,即将成为新的环境
newG={};
setmetatable(newG,{_index= _G});
将当前全局环境重新设置为新的table
setfenv(1,newG);
gName="我是新变量";
-- 输出值
print(gName);
print(_G.gName);
运行结果:nil
我是全局变量2
我是全局变量
Lua模块
1.一个简单的模块
--我们来看看一个简单的模块,新建一个文件命名为game.Iua,代码如下
game= {}
function game.play(
print("开始吧");
end
function game.quit()
print("结束了");
end
return game;
当我们使用的时候,需要用到我们前面讲过的require
game = require("game");
game.play();
2.最终解决方案
--我们来看看一个简单的模块,新建一个文件命名为game.Iua,代码如下
module("game",package.seeall)//module(...,package.seeall)
function play( )
print("开始吧")
end
function quit( )
print("结束了")
end
而package.sel参数的作用就是让原来的_G依然生效相当于调用了:setmetatable(M,{_index =_G});
当我们使用的时候,需要用到我们前面讲过的require
game = require("game");
game.play();
Lua面向对象的实现
定义类:
冒号的作用就是:定义函数时,给函数的添加隐藏的第一个参数self; 调用函数时默认把当前调用者作为第一个参数传递进去。
TSprite={x=0,y=0}
function TSprite:setPosition( x,y)
self.x=x
self.y=y
end
local who = TSprite
TSprite=nil
who:setPosition(1,2)
print(who.x,who.y)运行结果:1 2
单继承:
Hero={attack=0}
function Hero:new( o )
o=o or {}
setmetatable(o,self)
self.__index=self
return o
end
function Hero:skill( addAttack)
self.attack=self.attack+addAttack
return self.attack
end
oneHero=Hero:new({attack=100})
oneHero:skill(10)
print(oneHero:skill(10))运行结果 120
多重继承
function search( classes,key )
for i=1,#classes do
local value = classes[i][key]
if value ~= nil then
return value
end
end
end
function createClass( ... )
local parents = {...}
local num = #parents
local child = {}
if num == 1 then --单继承
setmetatable(child, {
__index = parents[1]
})
else --多继承
setmetatable(child, {
__index = function( table,key )
return search(parents, key)
end
})
end
return child
end
TSprite = {} --精灵类
function TSprite:new( o )
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function TSprite:hello( )
print("hello")
end
TBullet = {} --子弹类
function TBullet:new( o )
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function TBullet:fire( )
print("fire")
end
BulletSprite = createClass(TSprite,TBullet) --子弹精灵 继承上面两个类
function BulletSprite:new( o )
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function BulletSprite:say( )
print("i say")
end
local bSprite = BulletSprite:new({id = 2}) --实例化具体的对象
bSprite:hello()
bSprite:fire()
bSprite:say()
print(bSprite.id)
私密性
function createTSprite( )
local self = {name="myName"}
local function myBus( )
print("myBus是我 的函数,你不能直接调用")
end
local function myGame( )
print("myGame是我 的函数,你不能直接调用")
end
local function hello()
print("hello:")
myBus()
end
local function hi( )
myGame()
end
local function setName( newName )
self.name=newName
end
local function getName( )
return self.name
end
return{hello=hello,hi=hi,setName=setName,myBus=myBus,getName=getName}
end
local sp= createTSprite( )
sp.hello()
sp.hi( )
sp.myBus( )
-- sp.setName("100")
print( sp.getName())
运行结果:
hello:
myBus是我 的函数,你不能直接调用
myGame是我 的函数,你不能直接调用
myBus是我 的函数,你不能直接调用
myName
弱引用table
对于弱引|用table,其实有三种形式:
1.key值弱引|用,也就是刚刚说到的情况,只要其他地方没有对key值3引|用,那么,table自身的这个字段也会被删除。设置方法:setmetatable(t,{_mode="k" });
2.value值弱引|用,情况类似,只要其他地方没有对value值引|用,那么,table的这个value所在的字段也会被删除。设置方法:setmetatable(t,{_mode=“v" });
3.key和value弱引|用,规则一样但是key和value都同时生效任意一个起作用时都会设置方法:setmetatable(t,{_mode=
"kv" });导致table的字段被删除。
当然,这里所说的被删除,是指在Lua执行垃圾回收的时候并不一定是立刻生效的。
t={}
setmetatable(t,{__mode="v"})
key1={name="key1"}
t[key1]=1
key1=nil
key2={name="key2"}
t[key2]=2
key2=nil
强制进行一次垃圾收集
collectgarbage();
for key ,value in pairs (t) do
print(key.name ..":" ..value)
end
key1:1
key2:2