国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Lua - Lua中的metatable詳解

Lua中的metatable詳解

2020-04-15 10:33腳本之家 Lua

這篇文章主要介紹了Lua中的metatable詳解,本文詳細講解了metatable的作用、定義操作符行為、為 Lua 函數庫提供支持等內容,需要的朋友可以參考下

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

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

Metatables 定義操作符行為

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

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

 

復制代碼 代碼如下:

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

 

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

 

復制代碼 代碼如下:

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

 

每個算術操作符有對應的 metamethod:

 

+

__add

*

__mul

-

__sub

/

__div

-

__unm (for negation)

%

__mod

^

__pow

 

對于連接操作符有對應的 metamethod:__concat

同樣,對于關系操作符也都有對應的 metamethod:

 

==

__eq

<

__lt

<=

__le

 

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

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

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

為 Lua 函數庫提供支持

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

 

復制代碼 代碼如下:

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 函數,它們定義和使用了 __metatable 域。如果你希望設定的 value 的 metatable 不被修改,那么可以在 value 的 metatable 中設置 __metatable 域,getmetatable 將返回此域,而 setmetatable 則會產生一個錯誤:

 

復制代碼 代碼如下:

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

 

看一個完整的例子:

 

復制代碼 代碼如下:

Set = {}
 
local mt = {}
 
function Set.new(l)
    local set = {}
    -- 為 Set 設置 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 的第二個參數為 level
        -- level 指定了如何獲取錯誤的位置
        -- level 值為 1 表示錯誤的位置為 error 函數被調用的位置
        -- level 值為 2 表示錯誤的位置為調用 error 的函數被調用的地方
        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 會嘗試調用 __index metamethod。__index metamethod 接受兩個參數 table 和 key:

復制代碼 代碼如下:

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 中訪問對應的域:

 

復制代碼 代碼如下:

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

 

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

__newindex metamethod

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

1.如果 __newindex 為函數,Lua 將調用函數而不是進行賦值
2.如果 __newindex 為一個 table,Lua 將對此 table 進行賦值

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

結合 __index 和 __newindex 可以實現很多功能,例如:

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

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

 

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

 

復制代碼 代碼如下:

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

 

延伸 · 閱讀

精彩推薦
  • LuaLua教程(二):基礎知識、類型與值介紹

    Lua教程(二):基礎知識、類型與值介紹

    這篇文章主要介紹了Lua教程(二):基礎知識、類型與值介紹,本文講解了Hello World程序、代碼規范、全局變量、類型與值等內容,需要的朋友可以參考下 ...

    腳本之家5922020-04-28
  • LuaLua簡介、編譯安裝教程及變量等語法介紹

    Lua簡介、編譯安裝教程及變量等語法介紹

    這篇文章主要介紹了Lua簡介、編譯安裝教程及變量等語法介紹,本文同時講解了lua注釋語法、Lua命令行方式等內容,需要的朋友可以參考下 ...

    junjie3632020-04-14
  • Lua深入探究Lua中的解析表達式

    深入探究Lua中的解析表達式

    這篇文章主要介紹了深入探究Lua中的解析表達式,對于其語法部分的說明和示例都超詳細,極力推薦此文!需要的朋友可以參考下 ...

    腳本之家3542020-05-05
  • LuaLua和C語言的交互詳解

    Lua和C語言的交互詳解

    這篇文章主要介紹了Lua和C語言的交互詳解,Lua和C語言通過棧完成交互,本文結合代碼實例詳細講解了交互的方法,需要的朋友可以參考下 ...

    果凍想3702020-04-14
  • LuaLua中計算、執行字符串中Lua代碼的方法

    Lua中計算、執行字符串中Lua代碼的方法

    這篇文章主要介紹了Lua中計算、執行字符串中Lua代碼的方法,類似JavaScript中eval函數的功能,在Lua中也可以實現,需要的朋友可以參考下 ...

    腳本之家6322020-04-30
  • LuaLua中的元方法__newindex詳解

    Lua中的元方法__newindex詳解

    這篇文章主要介紹了Lua中的元方法__newindex詳解,本文講解了查詢與更新、監控賦值、通過table給另一個table賦值等內容,需要的朋友可以參考下 ...

    笨木頭8872020-04-09
  • LuaLua中table庫函數方法介紹

    Lua中table庫函數方法介紹

    這篇文章主要介紹了Lua中table庫函數方法介紹,本文講解了concat、insert、maxn、remove、sort、foreachi等方法,需要的朋友可以參考下 ...

    腳本之家2502020-04-17
  • LuaLua實現__add方法重載示例

    Lua實現__add方法重載示例

    這篇文章主要介紹了Lua實現__add方法重載示例,本文直接給出實現代碼,需要的朋友可以參考下 ...

    腳本之家7452020-04-24
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 欧美日韩第一页 | 91精品国产高清一区二区三区 | av在线精品 | 国产精品美女久久久久久免费 | 91资源在线观看 | 欧美精品久久 | 午夜久久乐 | 欧美日韩一区二区三区在线观看 | 国产精品免费网址 | 激情五月婷婷综合 | 久久综合中文字幕 | 久草最新| 国产亲子乱弄免费视频 | 欧美在线不卡 | 淫片在线观看 | 中文字幕日韩欧美一区二区三区 | 亚洲电影第二页 | 黄色毛片a | 亚洲影音 | 亚洲国产精品99久久久久久久久 | 欧美另类视频在线 | 91久久久久久久久 | 91精品一区二区三区久久久久久 | 国产欧美综合一区二区三区 | 日韩欧美在线观看视频 | 国产精品一区在线观看 | 亚洲视频在线免费观看 | 视频黄色免费 | 综合久久网| 亚洲毛片在线观看 | 五月婷婷激情网 | 日韩www| 中文字幕视频在线 | jvid精品资源在线观看 | 亚洲欧美日韩精品久久奇米色影视 | 国产精品一区视频 | 91亚洲国产成人久久精品网站 | 日本精品视频一区二区 | 中文字幕人成乱码在线观看 | 在线观看黄色 | 国产福利一区二区三区视频 |