欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Lua中的元表和元方法

 更新時(shí)間:2023年09月11日 08:40:04   作者:江澎涌  
Lua中的元表(Metatable)和元方法(Metamethods)是Lua語(yǔ)言中的重要概念,它們?cè)试S我們對(duì)對(duì)象和操作進(jìn)行自定義,本文講給大家詳細(xì)介紹一下Lua中的元表和元方法,需要的朋友可以參考下

一、元表

元表可以修改一個(gè)值在面對(duì)一個(gè)未知操作時(shí)的行為,Lua 中使用 table 作為元表的承載。

元表只能給出預(yù)先定義的操作集合的行為,比類會(huì)更加受限制,不支持繼承。

Lua 每一個(gè)值都可以有元表

  • 表和用戶數(shù)據(jù)類型都具有各自獨(dú)立的元表;
  • 其他類型的值則共享對(duì)應(yīng)類型所屬的同一個(gè)元表;

二、元表的設(shè)置

1、類型的原始元表

Lua 中,元表的設(shè)置只能針對(duì) table ,其他類型都不能設(shè)置。

table 的初始化元表為 nil ,即沒有設(shè)置元表,只能通過 setmetatable 進(jìn)行設(shè)置,多個(gè) table 可以共享一個(gè) table 作為元表(當(dāng)然也可以使用他自己作為自己的元表,因?yàn)樗陨硪彩且粋€(gè) table)

Lua 只有 string 初始化了元表,而且是針對(duì)了所有的字符串,即 string 都是同一個(gè)元表。其他的類型為 nil 。

print("表的初始值", getmetatable({}))           --> 表的初始值	nil
print("整型的初始值", getmetatable(10))         --> 整型的初始值	nil
print("浮點(diǎn)型的初始值", getmetatable(10.0))      --> 浮點(diǎn)型的初始值	nil
--- 通過打印可以看到兩個(gè)字符串的元表是同一個(gè)
print("字符串的初始值", getmetatable("江澎涌"))   --> 字符串的初始值	table: 0x600000b14640
print("字符串的初始值", getmetatable("jiangpengyong"))  --> 字符串的初始值	table: 0x600000b14640
print("布爾型的初始值", getmetatable(true))     --> 布爾型的初始值	nil
print("nil的初始值", getmetatable(nil))         --> nil的初始值	nil
function sayHello()  end
print("函數(shù)的初始值", getmetatable(sayHello))   --> 函數(shù)的初始值	nil

2、設(shè)置元表和獲取元表

2-1、setmetatable(table, metatable)

給表 table 設(shè)置元表 metatable

參數(shù)

  • table:要被設(shè)置元表的表
  • metabale:元表,如果值為 nil ,則表明要?jiǎng)h除 table 的原有元表。如果原來的元表有 __metatable 字段,則不能再設(shè)置元表,否則會(huì)拋出異常 cannot change a protected metatable

__metatable 會(huì)在下面的 “表相關(guān)方法” 小節(jié)分享

返回值:

返回被設(shè)置元表的表,就是參數(shù) table

2-2、getmetatable(object)

如果 object 沒有元表,則返回 nil

如果對(duì)象 Object 有元表,且該元表有一個(gè) "__metatable" 字段,則返回關(guān)聯(lián)的值。否則,返回給定對(duì)象 Object 的元表

2-3、舉個(gè)例子

local oriTable = {}
local metaTable = {}
print(setmetatable(oriTable, metaTable), oriTable, metaTable)       --> table: 0x600001ac0840	table: 0x600001ac0840
print(getmetatable(oriTable), metaTable)                            --> table: 0x600001ac0900	table: 0x600001ac0900

給元表帶有 __metatable 字段的表,設(shè)置新的元表,則會(huì)拋出異常(見下圖)

t2 = { c = 1 }
t2.__metatable = { a = 1 }
s1 = {}
setmetatable(s1, t2)
print('getmetatable(s1)["a"]', getmetatable(s1)["a"])           --> getmetatable(s1)["a"]	1
-- 此處會(huì)拋出異常:cannot change a protected metatable
print(setmetatable(s1, {}))

三、元表方法

1、具有的元方法

元表方法方法很像 kotlin 中的操作符方法

1-1、算術(shù)運(yùn)算符

元表方法含義
__add加法
__mul乘法
__sub減法
__div除法
__floorfloor除法
__unm負(fù)數(shù)
__mod取模
__pow冪運(yùn)算
__band按位與
__bor按位或
__bxor按位異或
__bnot按位取反
__shl向左移
__shr向右移
__concat定義連接運(yùn)算符

1-2、關(guān)系運(yùn)算符

元表方法含義
__eq等于
__lt小于
__le小于等于

值得注意: ~=、a > ba >= b 沒有對(duì)應(yīng)的元方法,會(huì)被轉(zhuǎn)為如下

  • a ~= b 會(huì)被轉(zhuǎn)為 not( a == b)
  • a > b 會(huì)被轉(zhuǎn)為 b < a
  • a >= b 會(huì)被轉(zhuǎn)為 b <= a

關(guān)系運(yùn)算符遇到兩個(gè)不同類型的對(duì)象,則會(huì)直接返回 false ,不會(huì)進(jìn)行搜尋任何的元方法

1-3、庫(kù)相關(guān)方法

元表方法含義
__tostring當(dāng)調(diào)用 tostring 時(shí),會(huì)先檢查值是否有一個(gè)元方法 __tostring ,有則會(huì)先使用。
__metatable使用該元方法可以保護(hù)元表,用戶無法獲取也無法修改該元表。當(dāng)元表設(shè)置了 __metatable 的字段,則 getmetatable 會(huì)返回這個(gè)字段的值,而 setmetatable 則會(huì)引發(fā)錯(cuò)誤
__pairs從 Lua 5.2 開始,當(dāng)元表?yè)碛幸粋€(gè) __pairs 的元方法時(shí),pairs 會(huì)調(diào)用這個(gè)元方法來完成遍歷

1-4、表相關(guān)方法

元表方法含義
__index一旦訪問 table 中不存在的字段,正常情況下會(huì)返回 nil 。如果設(shè)置了這個(gè)元表方法,則會(huì)調(diào)用自身元表對(duì)應(yīng)的該 __index 元方法,并以被調(diào)用的表(即此處的 table ,不是元表)和鍵作為參,進(jìn)行調(diào)用。也可以給 __index 設(shè)置一個(gè) table,這樣就會(huì)直接在這table 中查詢,速度比方法稍快。可以通過 rawget 獲取原始數(shù)據(jù),不考慮元表。
__newindex當(dāng)調(diào)用 table 進(jìn)行索引賦值時(shí),如果設(shè)置了該元表方法,則會(huì)使用被調(diào)用的表(即此處的 table ,不是元表),鍵和值作為參,調(diào)用該方法。同樣也可以給 __newindex 設(shè)置一個(gè)表,則會(huì)將值直接存至該表??梢酝ㄟ^ rawset(talbe, key, value) 相當(dāng)于 table[key] = value 進(jìn)行直接對(duì) table 的賦值,不考慮元表。
__len獲取 table 的長(zhǎng)度時(shí),會(huì)調(diào)用該方法,獲取長(zhǎng)度

__index__newindex 的異同

  • 相同點(diǎn):兩個(gè)函數(shù)都是發(fā)生在 table 中沒有對(duì)應(yīng)的 key 時(shí)觸發(fā)
  • 不同點(diǎn):當(dāng)前需要的索引沒有對(duì)應(yīng)的值時(shí)則調(diào)用 __index ,如果 table 設(shè)置值時(shí),則調(diào)用 __newindex

2、元方法的搜索

如果兩個(gè)變量相加,搜索規(guī)則如下:

  • 先查看第一個(gè)值是否有元表,并且是否存在所需元方法,如果存在則使用該元方法,此時(shí)第二個(gè)值的元方法被忽略。否則進(jìn)入下一條
  • 查看第二個(gè)值是否有元表,并且是否存在所需的元方法,如果有則進(jìn)行使用。否則進(jìn)入第三條
  • 拋出異常

3、舉個(gè)例子

這里元方法比較多,就不一一粘貼代碼了,不然會(huì)讓文章非常冗長(zhǎng)。建議各位童鞋們移步 github clone 下代碼自行運(yùn)行一下會(huì)更加深刻理解。

“算術(shù)運(yùn)算符” 、 “關(guān)系運(yùn)算符”、“庫(kù)相關(guān)方法” 相關(guān)的代碼 可以查看以下的代碼:

集合.lua:github.com/zincPower/l…

集合調(diào)用.lua:github.com/zincPower/l…

“表相關(guān)方法” 相關(guān)的代碼

表相關(guān)元方法.lua:github.com/zincPower/l…

四、寫在最后

以上就是詳解Lua中的元表和元方法的詳細(xì)內(nèi)容,更多關(guān)于Lua元表和元方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論