Lua——3.元表Metatable

lua的metatable也是一个普通的表,lua提供metatable的功能,主要有一下几种作用:

  1. 控制对 table 的访问
  2. 为 Lua 函数库提供支持
  3. 重载算数运算符和关系运算符的行为

    1.使用metatable控制对table的访问

    当查询table的某个键的时候,如果该table的这个键没有值,那么Lua就会寻找该table的metatable中的__index元方法:如果__index指向一个table,Lua会在此table中查找相应的键, 并且,__index也可以指向一个方法

当对table的某个键进行赋值时,如果该table存在该字段则为之赋值,若没有,那么Lua就会寻找该table的metatable中的__newindex元方法:如果__newindex指向一个table时,Lua会对这个table进行赋值操作,如果__newindex指向一个方法,Lua则会调用该方法

lua中的__index元方法

如果__index包含一个表格,Lua会在此表格中查找相应的键。

并且,__index可以指向一个表也可以指向一个方法

__index指向表时:

之前我们需要知道,当我们在一个表中查找一个元素时

首先在该表中查找,有则返回对应值,无则查看该表是否有元表metatable

若无元表则返回nil

有元表时,lua并不是在其元表中查找,而是在其元表的__index域中查找

因此:仅使用setmetatable()方法设置元表,并不能取得对应元表中的元素

BaseClass = {theKey1 = "the string value1"}
--[[
DerivedClass = {}
setmetatable(DerivedClass,BaseClass)
]]--
--注释的两句可简写为:
DerivedClass = setmetatable({},BaseClass)

res = DerivedClass.theKey1
print(res)

设置对应元表的__index键之后:

BaseClass = {theKey1 = "the string value1"}
BaseClass.__index = BaseClass
DerivedClass = setmetatable({},BaseClass)
res = DerivedClass.theKey1
print(res)

也可以换一种简写方法:

BaseClass = {theKey1 = "the string value1"}
DerivedClass = setmetatable({},{__index = BaseClass})    --即直接设  AnonymousTable = {__index = BaseClass} 为DerivedClass的元表,查找时可直接在AnonymousTable中的__index域对应的表BaseClass中查找
res = DerivedClass.theKey1
print(res)

所以,lua中的继承可以表示为:

local Car = {}
Car.__index = Car
function Car:new(o)
    o = o or {}
    setmetatable(o,Car)
    return o
end
function Car:run()
    print("Car‘s run func.")
end
--直接调用“父类”中的run方法
Car.run()

local FordCar = Car:new()
--子类调用“父类”中的run方法
FordCar.run()

--重写fordCar中的run方法
function FordCar:run()
    print("FordCar‘s run func.")
end
--重写之后调用
FordCar.run()

__index指向一个方法时

__index指向一个方法时,在我们访问该 table 的不存在的域时,Lua 会尝试调用 __index 元方法metamethod (__index metamethod 可以接受两个参数 table 和 key)

local t1 = {}
t1.__index = function(table,key)
    print("call the __index metamethod")
    print("table"..tostring(table))
    print("key"..key)
    return key.." from the __index"
end
--set t1 as t2‘s metatable
local t2 = setmetatable({},t1)
--pass the table and the key to __indexmetamethod
local res = t2.key1
print("the result is :"..res)
print("------------------")
res = t2.key2
print("the result is :"..res)

__newindex元方法

如果对 table 的一个不存在的域赋值时,Lua 将检查 __newindex metamethod:

1.如果 __newindex 为函数,Lua 将调用函数而不是进行赋值(如果 __newindex 为一个函数,它可以接受三个参数 table key value。如果希望忽略 __newindex 方法对 table 的域进行赋值,可以调用 rawset(t, k, v))

2.如果 __newindex 为一个 table,Lua 将对此 table 进行赋值

--file:newindex.lua
local mt = {
    key1 = "key1‘s value"
}

local other = {
    key1 = "the old value"
}

mt.__index = mt
--[[
mt.__newindex = function()
    print "Can not set value"
end
--]]
mt.__newindex = other 

local t = setmetatable({},mt)

t.key1 = "the new value from the table t."
print(t.key1)
--对__newindex指向的table中的key1进行更新操作,但是table t 中仍然没有键key1,进行t.key1的查询时,查询的仍然是__index中对应的键key1的值
print(other.key1)

2. 为 Lua 函数库提供支持

Lua 库可以定义和使用 metamethod 来完成一些特定的操作

一个典型的例子是 Lua Base 库中 __tostring 函数,print 函数会调用此函数进行输出,调用print时,会检查并调用 __tostring metamethod

--file:tablelib.lua
local mt = {}
mt.__tostring = function(t)
    return ‘{‘..table.concat(t,‘,‘)..‘}‘
end

local t = {1,2,3}
print(t)
print("-----------------")

setmetatable(t,mt)
print(t)

3. 重载算数运算符和关系运算符的行为

//TODO 

原文地址:https://www.cnblogs.com/sylvan/p/8478366.html

时间: 2024-10-11 13:37:44

Lua——3.元表Metatable的相关文章

Lua的元表(metatable)

metatable允许我们改变table的行为 Lua中的每一个表都可以有metatable(后面我们将看到userdata也有Metatable) Lua默认创建一个不带metatable的新表 setmetatable(只能用于table)和 getmetatable(用于任何对象) 可以使用setmetatable函数设置或者改变一个表的metatable 任何一个表都可以是其他一个表的metatable 一组相关的表可以共享一个metatable(描述他们共同的行为) 一个表也可以是自身

lua元表(metatable)和元方法(metamethod)

元表概念: 引言:Lua中的每个值都有一套预定义的操作集合,如数字相加等.但无法将两个table相加,此时可通过元表修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定操作. 访问机制:一般的元方法都只针对Lua的核心,也就是一个虚拟机.它会检测一个操作中的值是否有元表,这些元表是否定义了关于次操作的元方法.例如两个table相加,先检查两者之一是否有元表,之后检查是否有一个叫“__add”的字段,若找到,则调用对应的值.“__add”等即时字段,其对应的值(往往是一个函数或是table

lua面向对象封装及元表(metatable)性能测试

Lua本身是没有面向对象支持的,但面向对象编程在逻辑复杂的大型工程却很有用.于是很多人用Lua本身的数据结构table来模拟面向对象.最简单的一种方法是把对象的方法.成员都放到table中.如: -- file:test.lua local test = {} function test:get_x() return self.x or 0 end function test:set_x( _x ) self.x = _x end local test_module = {} function

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元表Metatable

Lua 中的每个值都可以用一个 metatable. 这个 metatable 就是一个原始的 Lua table , 它用来定义原始值在特定操作下的行为. 你可以通过在 metatable 中的特定域设一些值来改变拥有这个 metatable 的值 的指定操作之行为. 举例来说,当一个非数字的值作加法操作的时候, Lua 会检查它的 metatable 中 "__add" 域中的是否有一个函数. 如果有这么一个函数的话,Lua 调用这个函数来执行一次加法. 我们叫 metatable

Lua中的元表(metatable)、元方法(metamethod)详解

在第一次看见这两样东西的时候,可能会觉得它很深奥,但其实很好理解,虽然实际上它可能真的很深奥.(小若:停!滚粗.) 1.知道为什么1 + 1 = 2吗? 为什么在Lua中,1+1会等于2呢?(小若:难道除了Lua,其他地方就不等于2了?)为什么数字和数字相加是合法的,为什么table和table相加就会报错?大家有想过这些问题吗? 没错,规则,这一切都只是规则而已,Lua规定了数字之间可以进行加减乘除,而table之间则不可以. 这是因为,在人类世界里,并没有table和table相加的概念. 

元表(metatable)

元表为重定义Lua中任意一个对象(值)的默认行为提供了一种公开入口. 如同许多OO语言的操作符重载或方法重载. 算术类元方法:     字段:__add  __mul  __ sub  __div  __unm  __mod  __pow  (__concat) 代码:(两个table相加) 下例中mt是元表,__add是元方法 tA = {1, 3} tB = {5, 7} --tSum = tA + tB mt = {} mt.__add = function(t1, t2) for _,

lua中对于metatable用法和原理的总结

<span style="font-family: Arial, Helvetica, sans-serif;">-- --metatable 可以作为继承的用法</span> parent = { house = 1 } parent.__index = parent --如果没有这一句话 child即使是设置parent为元表 也不能找到parent中的内容. __index指向的内容是nil child = { wife = 2 } setmetatabl

lua中的metatable和metamethod

--元表和元方法给lua里的值设定一些操作,让我们可以对这些操作自定义 --创建一个新的table变量时,它是不存在元表的 --在Lua中,只能设置table的元表,其他类型的值的元表,只能通过C代码来完成 local mt={} mt.__add=function(t1,t2)print("i am result")end local t1={} local t2={} setmetatable(t1,mt) setmetatable(t2,mt) local result=t1+t