zoukankan      html  css  js  c++  java
  • 全局变量声明的规范化

      Lua将环境本身存储在一个全局变量_G中,(_G._G等于_G)。为了对全局命名空间更好的管理,最好是显示的声明每一个变量,可以通过使用metamethod来改变_G的行为来进行规范:

    -- 声明新的变量,使用rawset绕过metamethod的限制
    -- 保证声明的变量不为nil,如果声明一个nil变量,等于该变量还是不存在,访问该变量的时候还是会触发__index
    declare = function(name, initval)
        rawset(_G, name, initval or false)
    end
    
    --改变全局变量的访问行为
    setmetatable(_G, 
        {__newindex = function (_, n)
        error("attempt to write to undeclared variable " ..n, 2)
        end,
        
        __index = function(_, n)
        error("attempt to read undeclared variable "..n, 2)
        end,}
    )
    
    declare("a")
    a = 1
    print(a)    -- 1
    a = nil
    print(a)    -- error 触发__index,因为该变量已经释放了

      上述代码中,每一个变量都需要显示declare,并且不能声明nil变量。

      下面这种方法可以声明nil变量,但需要用一个表来显示的记录每一个声明过的变量:

    local declareNames = {}
    function declare(name, initval)
        rawset(_G, name, initval)
        declareNames[name] = true
    end
    
    setmetatable(_G, 
        {__newindex = function (t, n, v)
            if not declareNames[n] then
                error("attempt to write to undeclared var. " ..n, 2)
            else
                rawset(t, n, v)
            end
        end,
    
        __index = function (_, n)
            if not declareNames[n] then
                error("attempt to read undeclared var. "..n, 2)
            else
                    return nil
            end
        end}
    )
    
    declare("a")
    a = 1
    print(a)        -- 1
    a = nil
    print(a)        -- nil 还是可以访问

      个人偏向于第一种方法,因为第二种方法中,当一个变量被置为nil以后,实际上该变量已经被释放了,所以将变量的置空操作封装在一个undeclear函数中。对第二种方法的改进:

    local declareNames = {}
    function declare(name, initval)
        rawset(_G, name, initval)
        declareNames[name] = true
    end
    
    function undeclare(name)
        declareNames[name] = nil
        rawset(_G, name, nil)
    end
    
    setmetatable(_G, 
        {__newindex = function (t, n, v)
            if not declareNames[n] then
                error("attempt to write to undeclared var. " ..n, 2)
            else
                rawset(t, n, v)
            end
        end,
    
        __index = function (_, n)
            if not declareNames[n] then
                error("attempt to read undeclared var. "..n, 2)
            else
                    return nil
            end
        end}
    )
    
    declare("a")
    a = 1
    print(a)        -- 1
    undeclare("a")
    print(a)        -- error 变量已经不存在了,会触发__index

      两种方法的代价都很小,可以忽略不计,但是给整个编程环境带来的好处是不言而喻的。

  • 相关阅读:
    常见的HTTP状态码(HTTP Status Code)说明
    Java基本数据类型和Integer缓存机制
    面向对象的三大基本特征和五大基本原则
    工程变更(ENGINEERING CHANGE)
    反射
    Redis学习手册(开篇)
    MVC,SSM与三层架构的构成及相互关系
    Java框架篇---Mybatis 入门
    java三大框架介绍
    WEB前端JS与UI框架
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/3838311.html
Copyright © 2011-2022 走看看