Lua
Metatable
元表就是一個集合了{__index, __add, __call}之類函數的表。 我把他理解爲在某個表內 內嵌的一個隱藏的表。只有在查找失敗的時候會用到,而且在查找失敗的時候並不是調用這個“隱藏表”裏的函數,而是這個“隱藏表”裏__index裏面裝的函數。
如果一個元素有元表,則查詢某個鍵的過程變爲
- 若表內存在該鍵,返回值;若不存在,進行下一步
- 若表內存在元表,進行下一步;返回nil
- 若元表內的__index裏有值,對__index執行第一步
-- top is actually {v = 1, top = 'top', __index = table-top, metatable = nil }
top = {}
top.__index = top
top.top = 'top'
top.v = 1
print('======= TOP ========')
print('top.top = ' .. top.top)
print('top.v = ' .. top.v)
-- {v = 1, top = 'top', __index = table-top, *hidden_table* = nil }
-- ^
-- mid is actually {v = 2, __index = table-mid, metatable = | }
mid = {}
mid.__index = mid
mid.v = 2
setmetatable(mid, top)
print('======= MID ========')
print('mid.top = ' .. mid.top) -- find failed, try to locate metatable.__index.top, which equals top.top
print('mid.v = ' .. mid.v)
print('mid.super.v = ' .. getmetatable(mid).v)
-- {v = 1, top = 'top', __index = table-top, *hidden_table* = nil }
-- ^
-- {v = 2, __index = table-mid, metatable = | }
-- ^
-- bot is { v = 3, __index = table-bot, metatable = | }
bot = {}
bot.__index = bot
bot.v = 3
setmetatable(bot, mid)
print('======= BOT ========')
print('bot.top = ' .. bot.top)
print('bot.v = ' .. bot.v)
print('bot.super.v = ' .. getmetatable(bot).v)
print('bot.super.super.v = ' .. getmetatable(getmetatable(bot)).v)
輸出結果
======= TOP ========
top.top = top
top.v = 1
======= MID ========
mid.top = top
mid.v = 2
mid.super.v = 1
======= BOT ========
bot.top = top
bot.v = 3
bot.super.v = 2
bot.super.super.v = 1
Inherit
自己寫了一個雞肋的繼承,繼承的基本結構是(箭頭表示元表指向)
mid -> Mid -> Top
mid 同時持有Mid和Top的成員變量,與c++不同的是:對於同名成員變量,這裏僅保存子類的值。
Top = {}
Top.__index = Top
function Top:create(v)
local top = {}
top.v = v
setmetatable(top, Top)
return top
end
function Top:print()
print("this is top")
print("v = " .. (self.v or 'nil'))
print("x = " .. (self.x or 'nil'))
end
Mid = {}
Mid.__index = Mid
setmetatable(Mid, Top)
function Mid:create(v, x)
-- mid -> Mid -> Top
local mid = Top:create(0)
setmetatable(mid, Mid)
mid.v = v
mid.x = x
return mid
end
function Mid:print()
print("this is mid")
print("v = " .. (self.v or 'nil?'))
print("x = " .. (self.x or 'nil?'))
Top.print(self)
end
top = Top:create(1)
mid = Mid:create(2, 3)
mid:print()
輸出結果爲
this is mid
v = 2
x = 3
this is top
v = 2
x = 3