博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
lua元表和元方法 《lua程序设计》 13章 读书笔记
阅读量:6036 次
发布时间:2019-06-20

本文共 3638 字,大约阅读时间需要 12 分钟。

lua中每个值都有一个元表,talble和userdata可以有各自独立的元表,而其它类型的值则共享其类型所属的单一元表。lua在创建table时不会创建元表。

t = {}print(getmetatable(t))  --显示过元表 此时是nil--可以用setmetatable来设置或修改任何table的元表t1 = {}setmetatable(t,t1)assert(getmetatable(t) == t1)

任何table可以作为任何值的元表,而一组相关的table可以共享一个通用的元表,此元表描述了一个共同的行为。一个tabel甚至可以作为它自己的元表,用于描述其特有行为。

在lua中,只能设置table的元表。要设置其它类型的元表,必须通过C代码来完成

print(getmetatable("hi"))  --005DECD8 说明字符串有元表print(getmetatable(10))  --number没有元表

13.1  算术类的元方法

Set = {}  --集合local mt = {}  --集合元表--根据参数列表中的值创建一个新的集合function Set.new(l)    local set = {}    setmetatable(set,mt)  --指定 table set的元表为mt    for k,v in ipairs(l) do        set[v] = true    --注意,是拿索来当数据用的    end    return setendfunction Set.union(a,b)    local res = Set.new{}    for k,v in pairs(a) do res[k] = true end    for k,v in pairs(b) do res[k] = true end    return resendfunction Set.intersection(a,b)    local res = Set.new{}    for k,v in pairs(a) do        if b[k] then            res[k] = true        end    end    return resendfunction Set.tostring(set)    local l = {}    for k,v in pairs(set) do        l[#l + 1] = k    end    return "{
" .. table.concat(l,", ") .. "}"endfunction Set.print(s) print(Set.tostring(s))end--将元方法加入元表mt.__add = Set.union --指定加号为求并集的方法mt.__mul = Set.intersection --指定乘号为交集的方法s1 = Set.new{
11,22,31,44,56}s2 = Set.new{
66,33,22,31}s3 = s1 + s2 --求并集 Set.print(s3) --输出 {11, 31, 66, 22, 33, 56, 44}s4 = s1 * s2 --求交集Set.print(s4) --输出 {31, 22}

13.2 关系类元方法

关系是指 __eq(等于)、__lt(小于)等

mt.__le = function(a,b)     for k in pairs(a) do        if not b[k] then  return false end     end     return trueendmt.__lt = function(a,b)    return a<=b and not (b<=a)endmt.__eq = function(a,b)    return a<=b and b<=aendss1 = Set.new{
2,4}ss2 = Set.new{
4,10,2}print(ss1<=ss2) --trueprint(ss1
=ss1) --trueprint(ss1>ss1) --falseprint(ss1 == ss2*ss1) --true

13.3 库定义的元方法

tostring是一个典型的实例。它能将各种类型的值表示为简单的文本格式

print({}) ----table: 003ECEF0

函数总是调用tostring来格式化输出。当格式化任意值时,tostring会检测该值是否有一个 __tostring元方法。如果有,他就调用这个方法用来作为tostring的返回值

在集合实例中,我们定议了将任命表示为字符串的方法,我们可以设置元表的__tostring字段

mt.__tostring = Set.tostring
sstext = Set.new{
33,55,6666}print(sstext) --{55, 33, 6666}

假设想要保护集合的元表,使用户即不能看也不能修改集合的元表。那么就需要用到__metatable。当设置了该字段时,getmetatable就会返回这个字段的值,而setmetatable会引发一个错误

mt.__metatable = "not your business"sstext1 = Set.new{}  print(getmetatable(sstext1))  --not your businesssetmetatable(s1,{})

13.4 table 访问的元方法

13.4.1 __index元方法

当访问一个table中不存在的字段中时,如果这个字段不存在得到nil,但是如果这个table有一个元方法__index那么如果没有这个字段,就由这个元方法来提供结果

Window = {}Window.prototype = {x=0,y=0,width = 100,height = 100}Window.mt = {}function Window.new(o)    setmetatable(o,Window.mt)    return oend--现在定义一个元方法Window.mt.__index = function(table,key)    return Window.prototype[key]endw = Window.new{x=10,y=20}print(w.width)  -- 100 window实际上没有width这个字段

__index元方法还可以是一个table

13.4.2  __newindex元方法

与__index不同的是__index是在查询的时候用的而_newindes是在更新的时候用的

13.4.3具有默认值的table

以下代码为table设置默认值

function setDefault(t,d)    local mt = {__index = function() return d end}    setmetatable(t,mt)end

13.4.4 跟踪table的访问

__index和__newindex都是在table中没有所需的index才发挥作用。因为只有table保持空才能捕捉到所有对他的访问,为了监视一个table的所有访问就得为真正的 table 创建一个代理

 

t_src = {}  --要跟踪的表local _t = t_srct = {} --创建代理--创建元表local mt = {    __index = function(t,k)        print("*access to element "  .. tostring(k))        return _t[k]    end,    __newindex = function(t,k,v)        print("*update of element " .. tostring(k) .. " to " .. tostring(v))        _t[k] = v    end}setmetatable(t,mt)t[2]  = "hello"  -- *update of element 2 to helloprint(t[2])  --*access to element 2

13.4.5 只读的table

只读table与上一节跟踪table类似,是通过__newindex来限制修改table内存

转载地址:http://sjohx.baihongyu.com/

你可能感兴趣的文章
Android如何实现超级棒的沉浸式体验
查看>>
使用node打造自己的命令行工具方法教程
查看>>
Express代理中间件问题与解决方案
查看>>
||和&&返回什么?
查看>>
linux在文件中查找指定字符串,然后根据查找结果来做进一步的处理
查看>>
在Oracle中删除所有强制性外键约束
查看>>
dhcp
查看>>
【R】R语言使用命令行参数 - [编程技巧(Program Skill)]
查看>>
经典算法题每日演练——第二题 五家共井
查看>>
存储过程中拼接的变量和点的问题
查看>>
ASP.NET那点不为人知的事(一)
查看>>
HTML 表格
查看>>
VMware 虚拟化编程(7) — VixDiskLib 虚拟磁盘库详解之三
查看>>
php 未实例化类调用方法的问题
查看>>
我对读计算机软件专业硕士的几点看法
查看>>
用JS写CSS
查看>>
TOJ4537: n阶行列式
查看>>
算法刷题笔记-stack-四则运算
查看>>
3.16
查看>>
Linux下arp用法
查看>>