码迷,mamicode.com
首页 > 其他好文 > 详细

lua学习笔记16:table元表详解

时间:2015-02-07 20:23:58      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:lua   元表   



一 table本质


Lua中table本质实际上是个类似HashMap东西。
其元素是很多的Key-Value对,类似iOS中的字典NSDictionary。
如果尝试访问了一个表中并不存在的元素时,就会触发Lua的一套查找机制。
lua“面向对象”就是凭借这个机制实现的。


示例:
local tab = {}
print(tab.key)


输出:nil


因为tab中没有任何元素,当然视图访问其key元素时就会找不到,所以返回nil。


二 元表metatable
元表,即元素列表,是table的一个备查找的元素列表;
当在table中找不到要访问的元素时,就会到它的元表中中区查找。
table的元表我们可以通过函数setmetatable来设置。


示例:
BaseClass = {
	base = 1,
}


DerivedClass = {
	derived = 2,
}
setmetatable(DerivedClass, BaseClass)
print(DerivedClass.base)


输出:
nil


已经设置了元表,还是找不到,这是为什么呢?往下看!


三 元方法__index
上面可以看到即使设置了元表,还是找不到元表中的元素,这是为什么呢?
因为当要在元表中查询元素的时间,并不是在元表中查找元表,而是在元表的__index中查找。


示例
print(DerivedClass.base)


输出:
1


另外,__index还可以是函数。
示例:
BaseClass = {
	base = 1
}
BaseClass.__index = function(tab, key)
	if key == "fun" then
		return 1
	else
		return 0
	end
end


DerivedClass = {
	derived = 2,
}
setmetatable(DerivedClass, BaseClass)
print(DerivedClass.fun)


输出:
1


上面的代码可以简写为:
BaseClass = {
	base = 1,
}
DerivedClass = setmetatable({derived = 2}, {__index = BaseClass})
print(DerivedClass.base)


-------------------------------------------------------------------------
BaseClass = {
	base = 1,
}
DerivedClass = setmetatable({derived = 2}, {__index = function(tab, key)
	if key == "fun" then
		return 1
	else
		return 0
	end
end})
print(DerivedClass.fun)




综上所述,可以发现如下规则:
1 __index方法用来确定表在被作为元表时的查找方法。
2 查找表元素时的过程如下:
a.在表中查找,如果找到,返回该元素,找不到则继续;
b.判断该表是否有元表,如果没有元表,返回nil,有元表则继续;
c.判断元表是否有__index方法,如果没有,则返回nil,有则继续查找;
d.如果__index方法是一个表,则重复a、b、c;
e.如果__index方法是一个函数,则返回该函数的返回值。


四 __newindex方法
当我们赋值时, 查找过程跟上面的一样。
如果都没有查找到,就会在元表metatable的__newindex中增加这个元素,然后赋值。


示例
BaseClass = {
	base = 1,
}
BaseClass.__index = BaseClass


NewElement = {}
BaseClass.__newindex = NewElement


DerivedClass = {
	derived = 2,
}
setmetatable(DerivedClass, BaseClass)


DerivedClass.new = 1


print(BaseClass.new)
print(NewElement.new)
print(DerivedClass.new)




输出:
nil
1
nil


因为DerivedClass里没有new,查看__newindex,并把new=1传给了NewElement,并没有给DerivedClass里的new赋值。




五 __call方法
__call 索引, 它允许你把表当函数调用。
示例:
BaseClass = {}
BaseClass.__call = function (BaseClass, a, b)
	return a + b;
end


DerivedClass = {
	derived = 2,
}
setmetatable(DerivedClass, BaseClass)
print(DerivedClass(1, 2))


输出:
3


六 __tostring方法
可以把表转化为string, 非常方便类似print的函数使用。 
BaseClass = {}
BaseClass.__tostring = function (BaseClass)
	local str = "-"
	for k, v in pairs(BaseClass) do
		str = str..">"..k..":"..v..""
	end
	return str
end


DerivedClass = {
	className = "DerivedClass",
	derived = 2,
}
setmetatable(DerivedClass, BaseClass)
print(DerivedClass)


输出:
->derived:2>className:DerivedClass

lua学习笔记16:table元表详解

标签:lua   元表   

原文地址:http://blog.csdn.net/xufeng0991/article/details/43608713

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!