Lua语言入门(四)

作者: 小飞不会飞_ | 来源:发表于2016-09-26 20:53 被阅读131次

    环境的概念

    45、环境:lua将其所有的全局变量(值、函数、table)保存在一个常规的table中,这个table称为环境,可以认为一个chunk只有一个环境,在lua5.2以后就不允许修改某个函数的环境了。全局变量存在一个叫 _G 的表中。环境的概念是针对全局变量的,对local变量无影响。

    利用table访问的元方法可以控制全局变量的访问

    --绕过元表,创建全局变量 a ,并赋值为“android”
    rawset(_G, "a", "android")
    print(a)
    
    --绕过元表判断是否存在全局变量 var
    if rawget(_G, var) == nil then
     print("not declare")
    end
    

    46、非全局的环境(特只自己创建的环境,不是全局环境(_G))
    修改函数的环境:setfenv,注意在lua5.3中去除了setfenv,有_ENV属性代替。

    a = 1
    --改变一个函数的环境,参数1可以为参数本身,也可以是数字,表示当前函数调用栈的层数,参数2表示新的环境table
    setfenv(1, {}) --1表示当前函数,2表示调用当前函数的函数,依次类推
    print(a) --这样就访问不到 a 了
    

    47、理解非全局环境:定义全局变量,默认被存储在当前环境中的,如果改变了环境,在新环境就没有以前环境下定义的函数变量等。使用全局变量时,不带表前缀(表名.)的,都是默认在当前环境中去找的。

    --local x = print --改变环境对local变量无影响
    x = print --定义x时的全局环境就是“全局环境”
    
    _ENV = {} --现在改变环境了,之前定义的全局变量都不在了 ,这个就是非全局环境
    a = 10 --这里定义的“全局变量 a”,是在当前环境中,也就是 “{}”
    x(a) --此时就访问不到 x 了,如果 x 是local的就可以访问
    

    非全局环境可以解决名字污染问题,也是lua封装的重要方法之一

    模块

    48、加载模块
    require函数:用于加载一个模块,如果传入的名字找到一个函数,则直接在加载;如果找到一个Lua文件,则用loadfile加载;如果找到一个C程序库,则用loadlib加载。

    --local m = require "mod" --mod是模块的名称
    --print(m.add(1, 2))
    require "mod"
    print(mod.add(1, 2))
    

    require查找的路径:存放在变量package.path中,当Lua启动后,便以环境变量LUA_PATH的值来初始化。

    判断name模块是否已加载:package.loaded[name],已经加载的模块会放在package.loaded中。

    49、编写模块的基本方法

    local modname = ... --其它地方使用require(name),...就是传递的name
    local M = {}
    _G[modname] = M --把M放在全局环境中,让其它地方可以用modname调用该模块
    --package.loaded[modname] = M --和末尾的return M 一样的功能
    
    --可定义一系列模块包含的功能
    
    M.add = function(a, b)
     return a+b
    end
    --
    
    --return M
    

    50、在模块中使用环境:上述的模块基本写法中,整个模块内部是在全局环境中的,如果不小心定义了全局变量,那么这个变量在任何加载该文件的地方都可以直接使用,不需要模块前缀,打破了模块的封装性,名字空间污染。

    --模块设置 
    local modname = ... --其它地方使用require(name),...就是传递的name
    local M = {}
    _G[modname] = M --把M放在全局环境中,让其它地方可以用modname调用该模块
    --package.loaded[modname] = M --和末尾的return M 一样的功能
    
    --导入段
    --声明这个模块从外界所需的所有东西
    local sqrt = math.sqrt
    local io
    
    --改变当前环境,这句话之后就不能访问全局环境中变量了,所以把需要用的外界的在上面先导入进来,注意是local变量存的
    _ENV = M
    
    --模块内容
    M.add = function(a, b)
     return a+b
    end
    
    return M
    

    面向对象编程

    51、类:在Lua中没有类的概念,每个对象只能自定义行为和形态。但可以用原型来模拟类的概念,因为在会在表的原型中查找它所没有的操作,就可以认为是原型定义了一系列操作,创建一个表并设置原型就近似创建了“对象”。

    让 a 的__index属性 等于 b,这样a 就会在 b 中查找所有它没有的操作,a 可以 称为 b的对象。

    setmatatable(a, {__index = b})
    

    “:”和“.”的区别:“:”会隐式的传递当前调用者

    a = {balance = 0}
    function a:f(v) --a:f(v) 等价于 a.f(self, v)
     self.balance = self.balance - v
    end
    
    b = a
    a = nil
    
    b:f(1) --b:f(1) 等价于 b.f(b, 1)
    
    面向对象的写法:
    a = {}
    function a:new(o)
     --“:”定义
     o = o or {}
     setmetatable(o, self)
     self.__index = self
     --让o的元表 self的__index属性等于自身,意味着 o 就会在 self 中查找所有它没有的操作
     return o
    end
    
    function a.f()
     print("a.f")
    end
    
    x = a:new()
     --“:”调用
    x.f()
    

    52、继承

    a = {} --创建基类a
    function a:new(o)
     o = o or {}
     setmetatable(o, self)
     self.__index = self --
     return o
    end
    
    function a.f()
     print("a.f")
    end
    
    b = a:new() --派生类b
    
    function  b.display()
     print("b.display")
    end
    
    c = b:new() --创建b类的对象 c
    

    所以啊,lua中类和对象本身没有区别,你可以叫 b、c 是对象,也可以认为它们是派生类。

    53、多重继承:如果__index是一个函数,之前学过,当访问一个表中不存在的操作时,就会调用元表中__index元方法返回结果。那么多重继承就是利用在 __index元方法中,查找所有继承的基类,是否存在相应的操作。

    local function search(k, plist)
     for i=1,#plist do
      local v = plist[i][k]
      if v then return v end
     end
    end
    
    function createClass(...)
     local c = {}
     local parents = {...}
    
     setmetatable(c, {__index = function(t, k)
       return search(k, parents)
      end})
    
     --c.__index = c
    
     function c:new(o)
      o = o or {}
      setmetatable(o, c)
      c.__index = c
      return o
     end
    
     return c
    end
    
    --创建新类
    mult = createClass()
    mult.fun = function()
     print("mult fun")
    end
    
    --创建对象
    a = mult:new()
    a.fun()
    
    

    相关文章

      网友评论

        本文标题:Lua语言入门(四)

        本文链接:https://www.haomeiwen.com/subject/gigqyttx.html