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
}

setmetatable(child, parent)
print(child.house)
print(child.wife)

parent.__newindex = function ( t, k ,v )
	-- t[k] = v
	if k == "house" then
		parent[k] = v * 2
	end
end
-- 等效于
-- parent.__newindex = parent 

child.house = 3
child.wife = 4

print(child.house)
print(child.wife)

parent.__index = nil 

child.house = 5
child.wife = 6

print(child.house)
print(child.wife)

--打印结果是:
-- 1
-- 2
-- 6
-- 4
-- nil
-- 6

2.metatable可以类似c++中重载操作符(重写元方法)   

f1 = { a = 1, b = 2 }
f2 = { a = 2 , b = 3 }

-- s = f1 + f2    现在的f1 和 f2 没有各自的__add函数
meta = {}

function meta.__add(f1, f2)
	local sum = {}
	sum.a = f1.a + f2.a
	sum.b = f1.b + f2.b
	return sum
end

setmetatable(f1, meta)
setmetatable(f2, meta)

s = f1 + f2
print(s.a)
print(s.b)

--需要重载的操作符
--算数类型
-- __add(a, b)                     for a + b
-- __sub(a, b)                     for a - b
-- __mul(a, b)                     for a * b
-- __div(a, b)                     for a / b
-- __mod(a, b)                     for a % b
-- __pow(a, b)                     for a ^ b
-- __unm(a)                        for -a
-- __concat(a, b)                  for a .. b
-- __len(a)                        for #a
--关系类型
-- __eq(a, b)                      for a == b
-- __lt(a, b)                      for a < b
-- __le(a, b)                      for a <= b
--table访问的元方法
-- __index(a, b)  <fn or a table>  for a.b
-- __newindex(a,b)
-- __newindex(a, b, c)             for a.b = c
-- __call(a, ...)                  for a(...)
-- 库定义的元方法
-- __metatable					    保护元表,不可读写
-- __tostring

3.metatable 可以当成一个类来使用

Parent = {}

function Parent:new()
	local newParent = { house = "white house" }
	self.__index = self
	return setmetatable(newParent, self)
end

function Parent:Wife( )
	print("mother live in the "..self.house )
end

parent = Parent:new()
parent:Wife()

--通过类似类的方式来继承
Child = Parent:new()
function Child:Position()
	local ChildHouse = self.house
	print("child live in the "..ChildHouse)
	self:Wife()
end

child = Child:new()
child:Position()

-- lua中检查某值得顺序:比如child 的house 属性。  先到Child中去检查有没有某个字段。就会去检索__index这个元方法。
-- 即当需要访问一个字段在table中不存在的时候,解释器会去查找一个叫__index的元方法,如果没有该元方法,那么访问结果就是nil,不然就由这个元方法来提供最终结果。

test1 = { param1 = 1}
test2 = { param2 = 2}
test3 = { param3 = 3}

-- test2.__index = test1  等价于:
test2.__index = function(testTable , key)
	-- print(testTable)
	-- print(test3)
	-- print(key)
	-- print(test1[key])
	return test1[key]
end
setmetatable(test3 , test2)

print(test3.param1)
print(test3.param2)
print(test3.param3)

-- 这里的__index赋值就相当于  test2.__index = test1

--注释部分打印得出的结果是:
-- table: 0x7fe038c05440
-- table: 0x7fe038c05440
-- param1
-- 1
-- nil
-- table: 0x7fe038c05440
-- table: 0x7fe038c05440
-- param2
-- nil
-- nil
-- 3

--testTable的地址和test3的地址相同 ,由此可知,__index这种元方法会有一个默认形参是该表本身。而这里setmetatable只是给表设置了元表,真正查询字段的是根据元表中__index元方法所指向的表中的字段。而不是元表中的字段。

这里有个问题没有搞清楚,多打印出来一个nil这个nil是什么?  如果有理解的同学请在下面留言,指点我一下。

4.metatable的结合应用

--具有默认值的应用
function setDefault (mainTabel , returnValue)
	local mt = {__index = function () return returnValue end }
	setmetatable(mainTabel , mt)
end

tab = { x = 10 ,y = 20}
print(tab.x , tab.y , tab.z)
setDefault(tab, 0)
print(tab.x , tab.y , tab.z)

--只读属性的table
function readOnly (t)
	local proxy = {}
	local mt = { __index = t, __newindex = function (t, k ,v) print("it's a readOnly table ") end}
	setmetatable(proxy , mt)
	return proxy
end

days = readOnly { 1 , 2 ,3 ,4 ,5 ,6 ,7}
print(days[1])

days[2] = 12
-- print(days[2])
时间: 2024-11-05 18:30:46

lua中对于metatable用法和原理的总结的相关文章

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

【转载】Lua中实现类的原理

原文地址 http://wuzhiwei.net/lua_make_class/ 不错,将metatable讲的很透彻,我终于懂了. ------------------------------------------------------------ Lua中没有类的概念,但我们可以利用Lua本身的语言特性来实现类. 下文将详细的解释在Lua中实现类的原理,涉及到的细节点将拆分出来讲,相信对Lua中实现类的理解有困难的同学将会释疑. 类是什么? 想要实现类,就要知道类到底是什么. 在我看来,

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

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

Lua中table类型的源码实现

  1.概述 table是lua中唯一的表示数据结构的工具.它可以用于实现数据容器.函数环境(Env).元表(metatable).模块(module)和注册表(registery)等其他各种用途.因此了解table的实现是非常有必要的,根据<Lua中数据类型的源码实现>中知道,在Lua中,table是由结构体体Table来实现的.下面将以Lua 5.2.1的源码来看table的实现.   2.实现原理 在Lua5.0以后,table是以一种混合型数据结构来实现的,它包含一个哈希表部分和一个数

Lua 安全调用 metatable 的简单应用

事情的经过 我们的项目中存在好几个战斗界面,不过界面中的内容略有不同.跟同事出去吃饭的时候,他问我.我们现在的战斗界面.有很多是重复的,但是也有偶尔几个地方不太一样.我在战斗过程中驱动这些界面的时候.还需要判断一下有没有这个函数,然后在选择调用它.比较麻烦,你说怎么样才能更好的规划这件事情呢?我第一个想到的就是抽离出来一个UI的父层对象.然后父层对象实现所有的函数.然后让父层函数hook住具体的页面.然后判断具体的页面究竟有没有这个函数,如果存在这个函数那么调用,否则什么都不做就行了.不过,我突

lua中的面向对象编程

简单说说Lua中的面向对象 Lua中的table就是一种对象,看以下一段简单的代码: 上述代码会输出tb1 ~= tb2.说明两个具有相同值得对象是两个不同的对象,同时在Lua中table是引用类型的.我在<Lua中的模块与包>中也总结了,我们是基于table来实现的模块,在table中可以定义函数,也就是说,每个table对象都可以拥有其自己的操作.看一段代码: 上面的代码创建了一个新函数,并将该函数存入Account对象的withDraw字段中,然后我们就可以调用该函数了.不过,在函数中使

Lua中的基本函数库

基本函数库为Lua内置的函数库,不需要额外装载 assert (v [, message])功能:相当于C的断言,参数:v:当表达式v为nil或false将触发错误,message:发生错误时返回的信息,默认为"assertion failed!" -------------------------------------------------------------------------------- collectgarbage (opt [, arg])功能:是垃圾收集器的通

Lua中的元表与元方法

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

Lua中的weak表——weak table(转)

弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak references,元素为弱引用的表就叫弱表.有弱引用那么也就有强引用,有引用那么也就有非引用.我们先要厘这些基本概念:变量.值.类型.对象. (1)变量与值:Lua是一个dynamically typed language,也就是说在Lua中,变量没有类型,它可以是任何东西,而值有类型,所以Lua中没