Lua 学习笔记(十一)元表与元方法

在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的字段)

在对table使用算术操作符时,Lua回去查找有没有操作符对应的元方法,如果有则调用算术类元方法,否则会产生错误信息。如

table1 = { x=1 }
table2 = { x=2 }
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中的元方法才会有效。

时间: 2024-10-11 05:27:57

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

lua metatable和metamethod元表和元方法

Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表达式a+b.当Lua试图将两个table相加时,它会先检查两者之一是否有元表,然后检查该元表中是否存在__add字段,如果有,就调用该字段对应的值.这个值就是所谓的“元方法”,这个函数用于计算table的和.    Lua中每个值都有一个元表.table和userdata可以有各自独立的元表,而其它数据类型的值则共享其类型所属的单一元表.缺省情况

Lua学习笔记-metatable元表

本以为看完C API lua就学的差不多了,没想到越陷越深啊. 首先说元表的概念,元表是一个特殊的表,作用是定义一个表的操作.类似于C++中类的运算符重载. 使用元表需要注意的事项: 1.元表可以定义的操作有下面这些 1 __add(a, b) --加法 2 __sub(a, b) --减法 3 __mul(a, b) --乘法 4 __div(a, b) --除法 5 __mod(a, b) --取模 6 __pow(a, b) --乘幂 7 __unm(a) --相反数 8 __concat

LUA Learning Note 6: 元表与元方法

--元表:是用来存放无方法的一个table. --table和userdata可以各种拥有独立的元表. 但是,其他类型的值就只能共享其类型所属的元表,比如,数字,所有的数字都共用一个元表. --元方法:用来进行table 类型变量进行特殊操作的一个方法. --Lua其实已经规定好了各种算术操作符的元方法名字:_add,_sub,_mul,_div,_unm,_mod,_pow. --使用步骤: -- 创建一个元表     local mt = {};     mt.__add = functio

第十三章 元表与元方法 Lua程序设计笔记

--第十三章 元表与元方法Lua中每个值都有一个表.table和userdata可以有各自独立的元表,其他类型的值共享一个元表.Lua中只能设置table的元表.若要设置其他类型的值的元表,则必须通过C代码来完成. --13.1算数类型的元方法 Set = {} local mt = {} --创建元表 function Set.new(l)--根据参数列表中的值创建一个新的集合 local set = {} setmetatable(set, mt) --设置元表 for _,v in ipa

Lua中的元表与元方法

前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理,两个table类型的变量,你是无法直接进行“+”操作的,如果你定义了一个指定的函数,就可以进行了.那这篇博文就是主要讲的如何定义这个指定的函数,这个指定的函数是什么?希望对学习Lua的朋友有帮助. Lua是怎么做的? 通常,Lua中的每个值都有一套预定义的操作集合,比如数字是可以相加的,字符串是可以连

Lua语言基础汇总(8) -- Lua中的元表与元方法

前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理,两个table类型的变量,你是无法直接进行“+”操作的,如果你定义了一个指定的函数,就可以进行了.那本文就是主要讲的是如何定义这个指定的函数,这个指定的函数是什么?希望对学习Lua的朋友有帮助. Lua是怎么做的? 通常,Lua中的每个值都有一套预定义的操作集合,比如数字是可以相加的,字符串是可以连接

[转]Lua中的元表与元方法

前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理,两个table类型的变量,你是无法直接进行“+”操作的,如果你定义了一个指定的函数,就可以进行了.那这篇博文就是主要讲的如果定义这个指定的函数,这个指定的函数时什么?希望对学习Lua的朋友有帮助. Lua是怎么做的? 通常,Lua中的每个值都有一套预定义的操作集合,比如数字是可以相加的,字符串是可以连

lua编程之元表与元方法

一. 前言 lua是一种非常轻量的动态类型语言,在1993年由由Roberto Ierusalimschy.Waldemar Celes 和 Luiz Henrique de Figueiredo等人发明,lua的设计目标是轻便地嵌入宿主语言,增强系统的可扩展性和可定制性.lua的源码只有两万余行,非常精简小巧,在目前的脚本引擎中,lua的速度是最快的,这也是lua进入程序设计语言前20名,如今已经广泛应用于游戏行业,这几篇文章将会讨论下lua的几个比较重要的特性. 一门语言的类型系统是其最根本

Lua学习笔记4:类及集成的实现

-- Lua中类的实现 -------------------------------- 基类 ---------------------------- classBase = {x = 0,y = 0} -- x,y为类的成员变量 classBase.__index = classBase -- 这句是重定义元表的索引,必须要有 --模拟构造体,一般名称为new() function classBase:new(x,y) local self = {}     -- 初始化对象自身 setme