国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院

首頁 > 開發(fā) > 綜合 > 正文

Lua中的metatable詳解

2024-07-21 23:04:16
字體:
供稿:網(wǎng)友

Lua 中 metatable 是一個普通的 table,但其主要有以下幾個功能:

1.定義算術(shù)操作符和關(guān)系操作符的行為
2.為 Lua 函數(shù)庫提供支持
3.控制對 table 的訪問

Metatables 定義操作符行為

Metatable 能夠被用于定義算術(shù)操作符和關(guān)系操作符的行為。例如:Lua 嘗試對兩個 table 進行加操作時,它會按順序檢查這兩個 table 中是否有一個存在 metatable 并且這個 metatable 是否存在 __add 域,如果 Lua 檢查到了這個 __add 域,那么會調(diào)用它,這個域被叫做 metamethod。

Lua 中每個 value 都可以有一個 metatable(在 Lua 5.0 只有 table 和 userdata 能夠存在 metatable)。每個 table 和 userdata value 都有一個屬于自己的 metatable,而其他每種類型的所有 value 共享一個屬于本類型的 metatable。在 Lua 代碼中,通過調(diào)用 setmetatable 來設(shè)置且只能設(shè)置 table 的 metatable,在 C/C++ 中調(diào)用 Lua C API 則可以設(shè)置所有 value 的 metatable。默認的情況下,string 類型有自己的 metatable,而其他類型則沒有:

 

復(fù)制代碼 代碼如下:

print(getmetatable('hi')) --> table: 003C86B8
print(getmetatable(10))  --> nil

 

Metamethod 的參數(shù)為操作數(shù)(operands),例如:

 

復(fù)制代碼 代碼如下:

local mt = {}
function mt.__add(a, b)
    return 'table + ' .. b
end
local t = {}
setmetatable(t, mt)
print(t + 1)

 

每個算術(shù)操作符有對應(yīng)的 metamethod:

 

+ __add
* __mul
- __sub
/ __div
- __unm (for negation)
% __mod
^ __pow

 

對于連接操作符有對應(yīng)的 metamethod:__concat

同樣,對于關(guān)系操作符也都有對應(yīng)的 metamethod:

 

== __eq
< __lt
<= __le

 

其他的關(guān)系操作符都是用上面三種表示:
a ~= b 表示為 not (a == b)
a > b 表示為 b < a
a >= b 表示為 b <= a

和算術(shù)運算符不同的是,關(guān)系運算符用于比較擁有不同的 metamethod(而非 metatable)的兩個 value 時會產(chǎn)生錯誤,例外是比較運算符,擁有不同的 metamethod 的兩個 value 比較的結(jié)果是 false。

不過要注意的是,在整數(shù)類型的比較中 a <= b 可以被轉(zhuǎn)換為 not (b < a),但是如果某類型的所有元素并未適當(dāng)排序,此條件則不一定成立。例如:浮點數(shù)中 NaN(Not a Number)表示一個未定義的值,NaN <= x 總是為 false 并且 x < NaN 也總為 false。

為 Lua 函數(shù)庫提供支持

Lua 庫可以定義和使用的 metamethod 來完成一些特定的操作,一個典型的例子是 Lua Base 庫中 tostring 函數(shù)(print 函數(shù)會調(diào)用此函數(shù)進行輸出)會檢查并調(diào)用 __tostring metamethod:

 

復(fù)制代碼 代碼如下:

local mt = {}
mt.__tostring = function(t)
    return '{' .. table.concat(t, ', ') .. '}'
end
 
local t = {1, 2, 3}
print(t)
setmetatable(t, mt)
print(t)

 

另外一個例子是 setmetatable 和 getmetatable 函數(shù),它們定義和使用了 __metatable 域。如果你希望設(shè)定的 value 的 metatable 不被修改,那么可以在 value 的 metatable 中設(shè)置 __metatable 域,getmetatable 將返回此域,而 setmetatable 則會產(chǎn)生一個錯誤:

 

復(fù)制代碼 代碼如下:

mt.__metatable = "not your business"
local t = {}
setmetatable(t, mt)
print(getmetatable(t)) --> not your business
setmetatable(t, {})
    stdin:1: cannot change protected metatable

 

看一個完整的例子:

 

復(fù)制代碼 代碼如下:

Set = {}
 
local mt = {}
 
function Set.new(l)
    local set = {}
    -- 為 Set 設(shè)置 metatable
    setmetatable(set, mt)
    for _, v in ipairs(l) do set[v] = true end
    return set
end
 
function Set.union(a, b)
    -- 檢查 a b 是否都是 Set
    if getmetatable(a) ~= mt or getmetatable(b) ~= mt then
        -- error 的第二個參數(shù)為 level
        -- level 指定了如何獲取錯誤的位置
        -- level 值為 1 表示錯誤的位置為 error 函數(shù)被調(diào)用的位置
        -- level 值為 2 表示錯誤的位置為調(diào)用 error 的函數(shù)被調(diào)用的地方
        error("attempt to 'add' a set with a not-set value", 2)
    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
 
function Set.intersection(a, b)
    local res = Set.new{}
    for k in pairs(a) do
        res[k] = b[k]
    end
    return res
end
 
mt.__add = Set.union
mt.__mul = Set.intersection
 
mt.__tostring = function(s)
    local l = {}
    for e in pairs(s) do
        l[#l + 1] = e
    end
    return '{' .. table.concat(l, ', ') .. '}'
end
 
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
 
local s1 = Set.new({1, 2, 3})
local s2 = Set.new({4, 5, 6})
print(s1 + s2)
print(s1 ~= s2)

 

控制 table 的訪問

__index metamethod

在我們訪問 table 的不存在的域時,Lua 會嘗試調(diào)用 __index metamethod。__index metamethod 接受兩個參數(shù) table 和 key:

復(fù)制代碼 代碼如下:

local mt = {}
mt.__index = function(table, key)
    print('table -- ' .. tostring(table))
    print('key -- ' .. key)
end
 
local t = {}
setmetatable(t, mt)
local v = t.a

 

__index 域也可以是一個 table,那么 Lua 會嘗試在 __index table 中訪問對應(yīng)的域:

 

復(fù)制代碼 代碼如下:

local mt = {}
mt.__index = {
    a = 'Hello World'
}
 
local t = {}
setmetatable(t, mt)
print(t.a) --> Hello World

 

我們通過 __index 可以容易的實現(xiàn)單繼承(類似于 JavaScrpit 通過 prototype 實現(xiàn)單繼承),如果 __index 是一個函數(shù),則可以實現(xiàn)更加復(fù)雜的功能:多重繼承、caching 等。我們可以通過 rawget(t, i) 來訪問 table t 的域 i,而不會訪問 __index metamethod,注意的是,不要太指望通過 rawget 來提高對 table 的訪問速度(Lua 中函數(shù)的調(diào)用開銷遠遠大于對表的訪問的開銷)。

__newindex metamethod

如果對 table 的一個不存在的域賦值時,Lua 將檢查 __newindex metamethod:

1.如果 __newindex 為函數(shù),Lua 將調(diào)用函數(shù)而不是進行賦值
2.如果 __newindex 為一個 table,Lua 將對此 table 進行賦值

如果 __newindex 為一個函數(shù),它可以接受三個參數(shù) table key value。如果希望忽略 __newindex 方法對 table 的域進行賦值,可以調(diào)用 rawset(t, k, v)

結(jié)合 __index 和 __newindex 可以實現(xiàn)很多功能,例如:

1.OOP
2.Read-only table
3.Tables with default values

Read-only table

復(fù)制代碼 代碼如下:

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{'Sun', 'Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat'}
print(days[1])
days[2] = 'Noday' --> stdin:1: attempt to update a read-only table

 

有時候,我們需要為 table 設(shè)定一個唯一的 key,那么可以使用這樣的技巧:

 

復(fù)制代碼 代碼如下:

local key = {} -- unique key
local t = {}
t[key] = value

 

 
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院
在线免费看av| 久热中文字幕| 中文字幕网站视频在线| 欧美精品日韩少妇| 亚洲网站一区| 亚洲成人av在线影院| www.91在线播放| 国产中文字幕av| 国产特级嫩嫩嫩bbb| 99久久免费精品国产免费| 亚洲欧美日韩综合精品网| 九九99精品| 国产91足控脚交在线观看| 日本欧洲一区| 国产午夜电影| 青青久在线视频免费观看| 中文字幕在线视频免费观看| 精品电影在线| 久久精品无码一区二区日韩av | 最近中文字幕mv免费高清在线| 国产视频福利在线| 一级二级三级在线观看| 美女网站在线观看| 精品99又大又爽又硬少妇毛片 | 在线观看国产福利视频| 国产永久在线观看| 亚洲日本久久久午夜精品| 国产一级黄色大片| 浪潮av一区| 夜色资源网av在先锋网站观看| 开心婷婷激情| 亚洲人在线播放| 国产国产国产国产国产国产 | 国产美女福利在线| 91三级在线| 国产黄色免费网站| 国产一区二区三区福利| 成视频年人免费看黄网站| jizz亚洲| 中文日本在线观看| 国产精品四虎| 国产欧美久久久久久久久| 麻豆国产在线视频| 欧美性猛交p30| 九九热视频在线| 国产中文字幕在线视频| 久草在线视频网| 国产美女av| 国产极品嫩模在线视频一区| 国产日韩网站| 在线观看av网站| 四虎成人免费观看在线网址| eeuss影院在线观看第一页| av中文字幕在线看| 欧美高清视频| 中文字幕视频免费在线观看| 最近免费中文字幕大全免费第三页 | 天海翼中文字幕| av天天在线| 精品中文字幕不卡在线视频| 中文字幕日本三级| 在线天堂中文| 黄网址在线播放免费| 国产黄色片在线观看| www.91av| 国产天堂在线播放视频| 亚洲男人网站| 1区不卡电影| 伊人精品影院| 2018av男人天堂| 国产l精品国产亚洲区在线观看| 伊人精品影院| 国产无遮挡又黄又爽免费网站| 中文av字幕| 中文字幕欧美日韩在线不卡| 在线国产91| 国产精品欧美色图| 青青青青在线| 91午夜视频| 88av在线| av中文天堂在线| 国产精品久久在线| 国产精品亚洲色图| 日本三级在线视频| 精品女厕厕露p撒尿| 美女av在线播放| av在线第一页| 精品无人乱码| 国产高清一区二区三区视频| www.狠狠操| 在线三级中文| 国产xxxxx| 69视频在线| 国产夫妻视频| 精品卡1卡2卡三卡免费网站| 91精品专区| 中文在线有码| av在线不卡网站| а√最新版在线天堂| 在线观看wwww| 国产国产人免费人成免费视频| 国产在线传媒| 国产一起色一起爱| 国产系列在线观看| 国产叼嘿网站免费观看不用充会员| 国产无遮挡又黄又爽免费网站| 久热中文字幕在线观看| 久久一本精品| 国产精品偷乱一区二区三区| 超碰在线观看免费| 欧美日韩不卡中文字幕在线| 就爱干草视频| 国产一起色一起爱| 中文岛国精品亚洲一区| 日本一二三区视频免费高清| 日韩在线天堂| 国产美女视频网站| 国产99在线|亚洲| av免费在线一区二区三区| аⅴ成人天堂中文在线| 黄网站在线观看高清免费| 国产精品探花在线| 精品街拍一区二区| 人人在线视频| 国产区成人精品视频| 四虎影院成人| 国产欧美黑人| 国内精品一区视频| 99高清免费国产自产拍| 日本一级理论片在线大全| 欧美日韩国产亚洲沙发| 国产女主播在线观看| www在线播放| 最近中文av字幕在线中文| 亚洲日本伊人| 国产videos| 国产人成高清视频观看| 免费a级毛片在线观看| 国产精品爱久久久久久久小说 | 毛片网站在线观看| 国产调教视频在线观看| 青青草原国产在线观看| 国产九色在线| 青青国产在线| 中文产幕区在线观看| 最近高清中文在线字幕在线观看| av男人的天堂网| 国产精品久久精品牛牛影视| 国产乱人视频免费播放| 天堂网中文在线| 999福利在线视频| 国产日产一区二区| 国产亚洲精品拍拍拍拍拍| 超碰在线中文| 九九热视频精品在线观看| 香蕉视频在线观看www| 国产高清视频在线| √天堂资源地址在线官网| 成年网在线观看免费观看网址| 精品国产美女福利到在线不卡| 国产区视频在线观看| 国产私人影院| 国产成人精品自线拍| 国产精品18久久久久网站| 国产精品入口麻豆免费看| 国产黄网站在线观看| 国产xxxxx| 亚洲精品少妇久久久久久| 中文在线有码| 四虎成年永久免费网站| 日本亚洲欧美| 国产女呦网站| 91资源在线观看| 精品欧美日韩一区二区| 伊人影院蕉久影院在线播放| 天天草天天草| 国产在线高清| 国产精品伦理一区二区三区| 99精品老司机免费视频| 日本视频在线| 国产视频第一区| av免费在线观看网站| 黄色国产网站在线观看| 国产色a在线观看| 精精国产xxxx视频在线| www在线视频观看| 国产剧情在线一区| 亚洲综合在线网| 国产在线视频网站| 91社区在线观看| 久久五月精品| 在线欧美一级视频| 国产一区久久精品| www.操操| 国产porny蝌蚪视频| 成视人a免费观看视频 | 国产黄色免费| 欧美日韩视频精品一区二区| 国产福利小视频在线观看| 在线视频二区|