Lua 元表、元方法
每一个类型都有一个元表。
table
和 userdata
可以有各自独立的元表
其他类型的值则共享其类型所属的单一元表
表(table)
是 Lua
中非常重要的基本数据类型,实现其他的一些编程技术概念的基础,如模块、包、类。通过语言提供的元表和元方法可以更改表的表现行为。
元方法
元方法 | 简单描述 |
---|---|
__metatable |
调用 setmetatable、getmetatable方法的时候会用到这个字段 |
__index |
当表中的索引不存在时,查找元表中是否设置了这个元方法 |
__newindex |
同上 |
__add |
+ |
__sub |
- |
__mul |
* |
__div |
/ |
__unm |
-(相反数) |
__mod |
% |
__pow |
^ |
__concat |
.. 连接操作符 |
__eq |
等于 |
__lt |
小于 |
__gt |
大于 |
__metatable |
保护作用 |
__tostring |
字符串化 |
总的来说,在程序中通过元方法
,可以: -
更改算符运算符
、关系运算符
作用于表时的行为 -
更改对表中的元素的访问行为,简单说是重载了,[]
,[]=
运算符
这两个特性在C++特性中看起来是运算符的重载
。与C++相比,Lua本身没有面向对象的支持,但是使用元方法,可以实现其中的继承,还可以实现其他的功能、如返回具有默认值的table、跟踪table访问、只读的table
继承
从原型窗口继承所有不存在的字段 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23Window = {} -- 名字空间
Window.prototype = {x = 0,y = 0,width = 300,height = 400}
Window.mt = {}
function Window.new(o)
-- body
setmetatable(o, Window.mt)
return o
end
Window.mt.__index = function(tabel,key)
print(key)
return Window.prototype[key]
end
w = Window.new{10,20}
print(w.height)
``
返回具有默认值的table
当访问Lua表中不存在的一个元素的时候默认的返回的是nil,如果不想返回nil,则可以利用使用__index
元方法更改返回值。可以使用下面几种方式
方式一 : 为每一个需要默认值的表创建一个新的元表
1 |
|
方式二 : 使用同一个元表,默认值在每个表的各自内部
当有很多表需要默认值的时候,方法一会创建大量的元表,降低效率,下面这种方法更合适。所有通过新元表解决方案都会有这个问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
local mt = {
__index = function(t,key)
return t.___
end
}
function set_default(t,default)
t.___ = default
setmetatable(t, mt)
end
tab = {x = 1,y = 2}
print(tab.x,tab.y)
set_default(tab,0)
print(tab.x,tab.y,tab.z)
防止索引冲突,可以改进为如下
1 |
|
跟踪table访问
1 |
|
可以改进如下: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21local index = {} -- 防止key 冲突
local _mt = {
__index = function(t,k)
print('access to element '..tostring(k))
return t[index][k]
end,
__newindex = function(t,k,v)
print("update element "..tostring(k).." to "..tostring(v))
t[index][k] = v
end
}
function proxy(t)
--todo
local proxy = {}
proxy[index] = t
setmetatable(proxy, _mt)
-- t = proxy -- 方便 t = proxy(t),proxy(t)两种形式的调用 --- error 已经是局部变量t,和外围t不是一回事,受到名字的影响
return proxy
end
只读的table
1 |
|
方案二
1 |
|