文章來自:http://www.cnblogs.com/nepaul/archive/2011/08/18/2143936.htmlhtml
引言:Lua中的每一個值都有一套預約義的操做集合,如數字相加等。但沒法將兩個table相加,此時可經過元表修改一個值的行爲,使其在面對一個非預約義的操做時執行一個指定操做。函數
訪問機制:通常的元方法都只針對Lua的核心,也就是一個虛擬機。它會檢測一個操做中的值是否有元表,這些元表是否認義了關於次操做的元方法。例如兩個table相加,先檢查二者之一是否有元表,以後檢查是否有一個叫「__add」的字段,若找到,則調用對應的值。「__add」等即時字段,其對應的值(每每是一個函數或是table)就是「元方法」。lua
__index:
查詢:訪問表中不存的字段
rawget(t, i)spa
__newindex:
更新:向表中不存在索引賦值
rawswt(t, k, v)prototype
代碼:code
1
2
3
4
5
6
7
8
9
10
11
12
|
--比較集合大小 <
mt = {}
function mt.__lt(tA, tB)
return
#tA < #tB
end
tA, tB = {3}, {1, 2}
setmetatable(tA, mt)
setmetatable(tB, mt)
print(tA < tB)
|
代碼:(兩個table相加)htm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
tA = {1, 3}
tB = {5, 7}
--tSum = tA + tB
mt = {}
mt.__add = function(t1, t2)
for
_, item
in
ipairs(t2)
do
table.insert(t1, item)
end
return
t1
end
setmetatable(tA, mt)
tSum = tA + tB
for
k, v
in
pairs(tSum)
do
print(v)
end
|
語法:setmetatable (table, metatable),對指定table設置metatable 【若是元表(metatable)中存在__metatable鍵值,setmetatable會失敗】對象
語法:tmeta = getmetatable (tab),返回對象的元表(metatable) 【若是元表(metatable)中存在__metatable鍵值,當返回__metatable的值】blog
代碼:繼承
1
2
3
4
5
6
7
8
9
10
11
|
print(getmetatable(
"lua"
)) -->table: 002F19B8
print(getmetatable(10)) -->nil
--使用__metatable能夠保護元表,禁止用戶訪問元表中的成員或者修改元表。
tA = {}
mt = {}
getmetatable(tA, mt)
mt.__metatable =
"lock"
setmetatable(tA, mt)
print(getmetatable(tA)) -->
lock
|
setmetatable(只能用於table)和getmetatable(用於任何對象)
算術類元方法: 字段:__add __mul __ sub __div __unm __mod __pow (__concat)
關係類元方法: 字段:__eq __lt(<) __le(<=),其餘Lua自動轉換 a~=b --> not(a == b) a > b --> b < a a >= b --> b <= a 【注意NaN的狀況】
貫穿《Programming in Lua》元表與元方法整張的實例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
<span style=
"font-family: 黑體;"
>--[[
Set = {}
mt = {} --元表
function Set.
new
(l)
local
set
= {}
setmetatable(
set
, mt)
for
_, v
in
ipairs(l)
do
set
[v] =
true
end
return
set
end
--================================================
function Set.tostring(
set
)
local l = {}
for
e
in
pairs(
set
)
do
l[#l + 1] = e
end
return
"{"
.. table.concat(l,
","
) ..
"}"
end
function Set.print(s)
print(Set.tostring(s))
end
--1 加(__add), 並集===============================
function Set.union(a, b)
--[[
if
getmetatable(a) ~= mt or getmetatable(b) ~= mt then
error(
"attemp to 'add' a set with a non-set value"
, 2) --error第二個參數的含義P116
end]]
local res = Set.
new
{}
for
k
in
pairs(a)
do
res[k] =
true
end
for
k
in
pairs(b)
do
res[k] =
true
end
return
res
end
s1 = Set.
new
{10, 20, 30, 50}
s2 = Set.
new
{30, 1}
--print(getmetatable(s1))
--print(getmetatable(s2))
mt.__add = Set.union
s3 = s1 + s2
--Set.print(s3)
--[[元表混用
s = Set.
new
{1, 2, 3}
s = s + 8
Set.print(s + 8)
]]
--2 乘(__mul), 交集==============================
function Set.intersection(a, b)
local res = Set.
new
{}
for
k
in
pairs(a)
do
res[k] = b[k]
end
return
res
end
mt.__mul = Set.intersection
--Set.print(s2 * s1)
--3 關係類===================================NaN的概念====
mt.__le = function(a, b)
for
k
in
pairs(a)
do
if
not b[k] then
return
false
end
end
return
true
end
mt.__lt = function(a, b)
return
a <= b and not (b <= a)
end
mt.__eq = function(a, b) --居然能這麼用!?----
return
a <= b and b <= a
end
g1 = Set.
new
{2, 4, 3}
g2 = Set.
new
{4, 10, 2}
print(g1 <= g2)
print(g1 < g2)
print(g1 >= g2)
print(g1 > g2)
print(g1 == g1 * g2)
--]]
--============================================
--4 table訪問的元方法=========================
--[[
--__index有關繼承的典型示例
Window = {}
Window.prototype = {x = 0, y = 0, width = 100, height}
Window.mt = {}
function Window.
new
(o)
setmetatable(o, Window.mt)
return
o
end
Window.mt.__index = function (table, key)
return
Window.prototype[key]
end
w = Window.
new
{x = 10, y = 20}
print(w.width)
--__index修改table默認值
function setDefault (t, d)
local mt = {__index = function ()
return
d end}
setmetatable(t, mt)
end
tab = {x = 10, y = 20}
print(tab.x, tab.z)
setDefault(tab, 0)
print(tab.x, tab.z)
--]]
--13.4.5 只讀的table
function readOnly(t)
local proxy = {}
local mt = {
__index = t,
__newindex = function(t, k, v)
error(
"attempt to update a read-only table"
, 2)
end
}
setmetatable(proxy, mt)
return
proxy
end
days = readOnly{
"Sunday"
,
"Monday"
,
"Tuesday"
,
"W"
,
"T"
,
"F"
,
"S"
}
print(days[1])
days[2] =
"Noday"
</span>
|