Lua面向對象程式設計
1、__index學習
【前置知識】
setmatatable:設定元表
setmetatable(table1, metatable)
metatable裡一般實作__index、__newindex、__add等元方法實作對table的某種操作
當__index為表時
通過鍵值通路table時,如果沒有這個鍵,那麼Lua就會尋找table的metatable中__index表裡的key鍵
性質很像繼承關系的父親
【代碼】
t1 = {area = 0}
t2 = setmetatable(t1, {__index = {width = 1}})
-- 此時t1 等價t2 有相同的位址空間
print(t1.area)
print(t1.width)
t1.area = 2
print(t2.area)
print(t2.width)
t2.width = 2
print(t1.area)
print(t1.width)
【運作結果】
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CO1UTO3IGO3EjYlRTNwU2YxYzX2ITNxMDMxMzLcJTMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
__index實作繼承關系
【代碼】
--繼承關系
Shape = {area = 0}
function Shape:new(o, side)
o = o or {}
setmetatable(o, self)
self.__index = self --保持繼承鍊,不加此行, t1就沒有__index元方法,下面的t2 = it:new({}, 4)會報錯
side = side or 0
o.area = side * side
return o
end
t1 = Shape:new({key1 = 1}, 3)
print("t1.area:", t1.area)
print("t1.key1:", t1.key1)
t2 = t1:new({key2 = 2}, 4)
print("t2.key1:", t2.key1)
print("t2.key2:", t2.key2)
t3 = t2:new({key3 = 3}, 5)
print("t3.key1:", t3.key1)
print("t3.key2:", t3.key2)
print("t3.key3:", t3.key3)
【運作結果】
當__index為函數時
通過table.key查找時,會将table和key作為參數傳給函數
【代碼】
t = setmetatable({key1 = "hsj"}, {__index = function(table, key)
if key == 'key2' then
return 'yes'
else
return 'no'
end
end})
print(t.key2)
【運作結果】
2、__newindex學習
正常的table當對表中一個不存的key進行指派,會産生一個新的key值儲存。當用了__newindex後,則table不會産生新的key值,而對metatable産生新的key儲存
【代碼】
t = {}
print("t.key:", t.key)
t1 = setmetatable({},{__newindex = t})
t1.key = 1
print("t1.key:", t1.key)
print("t.key:",t.key)
【運作結果】
__index和__newindex混合使用
【代碼】
t2 = {}
t = setmetatable({key1 = "hsj"}, {__index = function(table, key)
if key == 'key2' then
return 'yes'
else
return 'no'
end
end,
__newindex = t2
})
t.key2 = 2
print("t2.key2:", t2.key2)
print("t.key2:", t.key2)
【運作結果】
【私密性】
相當于private
__index和__newindex建立一個隻讀的table
--隻讀table
function readOnly(t)
local answer = {}
local mt = {
__index = t,
__newindex = function(t, k, v)
error("attempt to update a read-only table", 2)
end
}
setmetatable(answer, mt)
return answer
end
t1 = {1, 2, 3, 4, 5}
t2 = readOnly(t1)
print(t2[1])
t2[1] = 5 --無法修改
__call
__call 元方法在 Lua 調用一個值時調用。
self或表名均可
【代碼】
mytable = setmetatable({10}, {
__call = function(self, value)
print("value:", value)
end
})
print(mytable(10))
mytable = setmetatable({10}, {
__call = function(mytable, value)
print("value:", value)
end
})
print(mytable(10))
【運作結果】
重載__add元方法
--隻讀table
t = setmetatable({1, 2, 3},{
__add = function(self, newtable)
len1 = #self
len2 = #newtable
sum = 0
for i=1, len1 do
sum = sum + self[i]
end
for i=1, len2 do
sum = sum + newtable[i]
end
return sum
end
})
t1 = {2,3,4}
answer = t + t1
print("answer:", answer)
其他類似的元方法
__add(a, b) 對應表達式 a + b
__sub(a, b) 對應表達式 a - b
__mul(a, b) 對應表達式 a * b
__div(a, b) 對應表達式 a / b
__mod(a, b) 對應表達式 a % b
__pow(a, b) 對應表達式 a ^ b
__unm(a) 對應表達式 -a
__concat(a, b) 對應表達式 a .. b
__len(a) 對應表達式 #a
__eq(a, b) 對應表達式 a == b
__lt(a, b) 對應表達式 a < b