在Lua中的每个值都有一套预定义的操作集合。例如可以将数字相加,可以连接字符串,还可以在table中插入一对key-value等。但是我们无法将两个table相加,无法对函数作比较,也无法调用一个字符串。

     但是,Lua提供了元表与元方法来修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定的操作。例如,假设a和b都是table,通过元表可以定义如何计算表达式a+b。当Lua试图将两个table相加时,它会先检查两者之一是否有元表,然后检查该元表中是否有一个叫__add的字段。如果找到了该字段,就调用该字段对应的值。这个值也就是所谓的”元方法“,它应该是一个函数,用于计算table的和。
 
     Lua在创建一个新的table时不会创建元表。因此有两个函数可以获取与设置元表:
     setmetatable( t1,t2 ) 设置t1的元表为t2。
     getmetatable( t ) 获取t的元表。
 
     任何table都可以作为任何值的元表,而一组相关的table也可以共享一个通用的元表,此元表描述了它们共同的行为。一个table甚至可以作为它自己的元表,用于描述其特有的行为。总之,任何搭配形式都是合法的。
 
     在Lua中可以定义值的行为,那么就有相应的元方法:算术类的元方法、关系类的元方法、库定义的元方法以及table访问的元方法。
     1、算术类的元方法:__add(加)、__sub(减)、__mul(乘)、__div(除)、__unm(相反数)、__mod(取模)、__pow(乘幂)、__concat(连接操作符)
     2、关系类的元方法:__eq(等于)、__lt(小于)、__le(小于等于)
     3、库定于的元方法:__tostring(print时调用)、__metatable(设置后不可修改元表)
     4、table访问的元方法:__index(查询table)、__newindex(修改table的字段)、__mode(弱引用table)
 
     在对table使用算术操作符时,Lua回去查找有没有操作符对应的元方法,如果有则调用算术类元方法,否则会产生错误信息。如 
 
table1 = { x= }
table2 = { x= }
print( table1 - table2 ) --产生错误:attempt to perform arithmetic on global 'table1' (a table value)
 
如果设置了元表及元方法,就可以按照自己的意愿去处理(减法求值的例子):
 
 
     关系类的元方法在使用上同算术类的元方法一样,都是在有操作符操作时去查询元方法,其中有三个关系操作符没有单独的元方法,Lua会把
     1、a~=b   转化为 not( a==b )
     2、a>b     转化为 b<a
     3、a>=b   转化为 b<=a
 
     库定义的元方法的应用:__tostring
 
 
      库定义的元方法的应用:__metatable
 
 
     table访问的元方法:__index。当访问一个table中不存在的字段时,得到的结果为nil。这是对的,但并非完全正确。实际上,这些访问会促使解释器去查找一个叫__index的元方法。如果没有这个元方法,那么访问结果就是nil,否则,就由这个元方法来提供最终的结果。
 
 
table访问的元方法:__newindex。当对一个table中不存在的索引赋值时,解释器就会查找__newindex元方法。如果有这个元方法,解释器就调用它,而不是执行赋值。注意,Lua中有一个rawset(t,k,v)方法可以绕过元方法直接对table进行赋值。
 
 
     通过table访问的元方法,__index、__newindex搭配使用可以很轻易的实现面向对象。元方法在元表中设置,只有当table被设置为元表时,table中的元方法才会有效。
 
     table访问的元方法:__mode。设置table为弱引用table,并确定是key为弱引用或者value为弱引用。所谓若引用就是一种会被垃圾收集器忽视的对象引用。如果一个对象的所有引用都是弱引用,那么Lua就可以回收这个对象了,并且还可以以某种形式来删除这些弱引用本身。Lua用“弱引用table”来实现弱引用,一个弱引用table就是一个具有弱引用条目的table。如果一个对象只被一个弱引用table所持有,那么最终Lua是会回收这个对象的。
     一个table的弱引用类型是通过其元表中的__mode字段来决定的。这个字段的值为一个字符串:'k'(table的key是弱引用)、'v'(table中value是弱引用)。只要有一个key或value被回收了,那么它们所在的整个条目都会从table中删除。
 
tab1 = {}
tab2 = { __mode = 'k' }
--tab1中的key将会是弱引用
setmetatable( tab1,tab2 )

Lua 学习笔记(十一)元表与元方法的更多相关文章

  1. lua metatable和metamethod元表和元方法

    Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表达式a+b.当Lua试图将两个table相加时, ...

  2. Java学习笔记十一:Java中的方法

    Java中的方法 一:什么是方法: 所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块. 学过C语言或者其他语言的应该都知道函数这个东西,在Java中,其实方法就是函数,只不过叫法不同,在 ...

  3. Lua中的元表与元方法学习总结

    前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了"+"符号,就可以进行类的加法运算.在Lu ...

  4. 【游戏开发】小白学Lua——从Lua查找表元素的过程看元表、元方法

    引言 在上篇博客中,我们简单地学习了一下Lua的基本语法.其实在Lua中有一个还有一个叫元表的概念,不得不着重地探讨一下.元表在实际地开发中,也是会被极大程度地所使用到.本篇博客,就让我们从Lua查找 ...

  5. Lua中的元表与元方法

    [前言] 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理 ...

  6. lua元表与元方法

    lua中提供的元表(metatable)与元方法(metamethod)是一种非常重要的语法,metatable主要用于做一些类似于C++重载操作符式的功能. lua中提供的元表是用于帮助lua变量完 ...

  7. lua中 table 元表中元方法的重构实现

    转载请标明出处http://www.cnblogs.com/zblade/ lua作为游戏的热更新首选的脚本,其优势不再过多的赘述.今天,我主要写一下如何重写lua中的元方法,通过自己的重写来实现对l ...

  8. lua编程之元表与元方法

    一. 前言 lua是一种非常轻量的动态类型语言,在1993年由由Roberto Ierusalimschy.Waldemar Celes 和 Luiz Henrique de Figueiredo等人 ...

  9. Lua中的元表和元方法

    Lua中每个值都可具有元表. 元表是普通的Lua表,定义了原始值在某些特定操作下的行为.你可通过在值的原表中设置特定的字段来改变作用于该值的操作的某些行为特征.例如,当数字值作为加法的操作数时,Lua ...

随机推荐

  1. javascript的变量声明提升

    这篇随笔是对网上文章的整理吸收 1. javascript的作用域是函数,不是块 2. 在函数内部,javascript解释器会把var变量提升到当前域的最前面,但是函数体不会提升. 看下面例子: v ...

  2. 机器学习&深度学习资料

    机器学习(Machine Learning)&深度学习(Deep Learning)资料(Chapter 1) 机器学习(Machine Learning)&深度学习(Deep Lea ...

  3. 【转】你所不知道的Android Studio调试技巧

    这篇写Android studio debug技巧个人觉得写得不错,转自:http://www.jianshu.com/p/011eb88f4e0d# Android Studio目前已经成为开发An ...

  4. 2016huasacm暑假集训训练五 H - Coins

    题目链接:http://acm.hust.edu.cn/vjudge/contest/126708#problem/H 题意:A有一大堆的硬币,他觉得太重了,想花掉硬币去坐的士:的士司机可以不找零,但 ...

  5. 有了lisk,为什么我们还要做一个Asch?

    0 前言 首先要声明一点,我们和我们的一些朋友都是lisk的投资人和支持者,我们也相信lisk会成功. 事实上,lisk已经成功了一半,目前在区块链领域融资金额排行第二,仅次于以太坊. 那为什么我们还 ...

  6. 编写一个基本的连接池来实现连接的复用&一些工程细节上的优化

    package it.cast.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQL ...

  7. shell简单用法笔记(一)

    一.linux中主要用的bash shell:查看linux系统中支持的shell种类可用: vim /etc/shell 执行shel脚步的方式: 1.赋予脚步可执行权限,使用相对或绝对路径调用该脚 ...

  8. 对改善ABP的一些建议

    园子里有不少同学对ABP框架很感兴趣,而且也已经将ABP用在了商用项目中,有些可能还在操练阶段.一般来说,我们使用ABP默认的一些功能已经足够了,但还是有很多人想要自己拓展一些功能而自己实现不了或者说 ...

  9. Google分布式构建软件之一:获取源代码

    本文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但尊重作者版权,注名原文地址. 在Google,所有的产品都是在主干上开发的.这样的好处:每个人都可以查看和修改代码, ...

  10. .NET事件监听机制的局限与扩展

    .NET中把“事件”看作一个基本的编程概念,并提供了非常优美的语法支持,对比如下C#和Java代码可以看出两种语言设计思想之间的差异. // C#someButton.Click += OnSomeB ...