zoukankan      html  css  js  c++  java
  • lua 元表是个啥?

     1 function readOnly(t)
     2     local proxy = {}
     3     local mt = {
     4         __index = t,
     5         __newindex = function(t,k,v)
     6             error("attempt to update a read-only table")
     7         end
     8     }
     9     setmetatable(proxy,mt)
    10     return proxy
    11 end
    12 
    13 days = readOnly{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}
    14 print(days[1])
    15 days[2] = "Noday"

    —关于上面的只读表的运行过程解释

    1:首先readOnly这个函数调用的说明,这个调用有点与其他语言不一样,参数没有放在圆括号中” 函数名() “,

    而是直接跟了一个表的构造式,参看program in lua第五章 函数,最开始的前10句:

       一个函数若只有一个参数,并且此参数是一个字面字符串或者是一个table构造式,那么圆括号是可有可无的.

      days = readOnly{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}

    2:readOnly(t) 的形参 t,接收了 {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday}

      那么相当于 t = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday}

    3:紧接着 local proxy = {} 是一个局部的表,且是空表,它的元表为mt,是因为 setmetatable(proxy,mt)这句话。

      也就是说 proxy.__index = mt. __index这个字段是lua 为表内置的.

    4:紧接着 return proxy 那么就相当于 days = proxy,记住 proxy是空表

    5:print(days[1]) 相当于print(proxy[1]) ,但由于proxy[1]没有值,于是找它的元表 mt,而mt也没有 mt[1]对应的值,于是又找到__index 字段对应的值,于是就找到了之前t接收的匿名元表,然后就输出了Sunday,匿名元表就是{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday}

    6:当对其赋值时,同第5步一样,最终找到了__newindex, 而它的值是一个函数,于是执行了

      error("attempt to update a read-only table)

    7:上面的分析过程,就是lua解释这个脚本的过程,我们想象成,自己写了一个函数,当它接收那样一段脚本时,是像上面那样执行这么一个逻辑,把这么一个逻辑用一个概念总结,称之为元表,这就是元表的内函.

    8:那为什么要这样做呢?这个逻辑,实际上是面向对象语言中的,多态的逻辑。只不过像C++,这样的语言,把上面的这种寻找过程的代码,由编译器产生而已。多态是相对继承而言的,即父类指针,指向了子类的对象,在运行时发生的行为,与代码给我们的字面逻辑不一致.

    9:lua通过元表,来模拟面象对象的多态特性。

    --输出结果为:

    --[[

    Sunday

    lua: d:/test.lua:6: attempt to update a read-only table

    stack traceback:

            [C]: in function 'error'

            d:/test.lua:6: in function <d:/test.lua:5>

            d:/test.lua:15: in main chunk

            [C]: ?

    ]]—

    //-------------------------接下来分析一下 program in lua 第十三章的 13.1“算术类的元方法”------------------

    把代码里加了点打印语句,就好理解了,另外把for语句省掉的部分写完整了。这样对照结果,就不会迷糊了

    对于初学者来说,原版书写的真是有点"不够厚道"。我看了N遍.才明白.不过省掉应该是为了少返回值,少执行一些代码,提高效率吧。

    Set = {}
    local mt ={}
    function Set.new (l)
      local set = {}
      setmetatable(set, mt)
      for _, v in ipairs(l) do 
        print("<",_,">","(",v,")")
        set[v] = true 
      end
      return set
    end
    
    function Set.union(a,b)
      local res = Set.new{}
      for k ,v in pairs(a) do res[k] = true  print(k,res[k]) end
      for k ,v in pairs(b) do res[k] = true  print(k,res[k]) end
      return  res
    end
    
    function Set.intersection (a,b)
      local res = Set.new{}
      for k in pairs(a) do
        res[k] = b[k]
      end
      return res
    end
    
    function Set.tostring (set)
      local l = {}
      for e ,v in pairs(set) do
        print(e,"|----|", v)
        l[#l + 1] = e
      end
      return "{" .. table.concat(l,", ") .. "}"
    end
    
    function Set.print(s)
      print(Set.tostring(s))
    end
    
      
    s1 = Set.new{10,20,30,40,}
    s2 = Set.new{30,1}
    print(getmetatable(s1))
    print(getmetatable(s2))  
    
    mt.__add = Set.union
    
    s3 = s1 +s2
    
    print('-------')
    print(s3)
    print('-------')
    
    Set.print(s3)
      
    print(getmetatable(""))
      
    for n in pairs(_G) do print(n) end  
  • 相关阅读:
    学习进度
    移动端使用rem.js,解决rem.js 行内元素占位问题
    利用递归实现数组的扁平化
    ES6 新增声明变量的 var let const 的区别详解
    js学习笔记
    ajax中error函数参数与返回值详解 200 300 400 500
    处理 vue项目 打包后导致css文件引用静态目录路径异常的问题
    vue-cli3 配置 vue.config.js
    使用 vue-cli3 搭建一个项目
    vue-router params 和 query 的区别
  • 原文地址:https://www.cnblogs.com/activity-life/p/4284246.html
Copyright © 2011-2022 走看看