日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lua中的metatable

發布時間:2023/12/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lua中的metatable 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Lua中的metatable

Lua 中每個 值value(或者對象)都可以有一個 metatable(在 Lua 5.0 只有table和 userdata能夠存在 metatable)。每個 table和userdata value 都有一個屬于自己的 metatable,而其他每種類型的所有 value 共享一個屬于本類型的metatable。

先用一個示例檢查一下對象的metatable:

t = {} print(getmetatable(t)) --> nil print(getmetatable('a')) --> table: 0x7fce64c05000 print(getmetatable('b')) --> table: 0x7fce64c05000mt = {} setmetatable(t, mt) print(getmetatable(t) == mt) --> true

上面的字符類型擁有相同的metatable。


做一下整體的說明:
Lua 中的每個值或對象都可以擁有一個 metatable。這個 metatable 就是一個原始的 Lua table ,它用來定義對象在特定操作下的行為。

一個metatable 可以控制一個對象做數學運算操作、比較操作、連接操作、取長度操作、取下標操作時的行為,
而且metatable 中還可以擴展,比如定義一個函數,讓 userdata 作垃圾收集時調用它。
對于這些操作,Lua 都將其關聯上一個被稱作事件的指定鍵。
當 Lua 需要對一個值發起這些操作中的一個時,它會去檢查值中 metatable 中是否有對應事件。
如果有的話,鍵名對應的值(稱為metamethod元方法)將控制 Lua 怎樣做這個操作。

metatable通過其包含的函數來給所掛接的table定義一些特殊的操作,包括下面的meta-method:

數學運算方法

  • __add: 定義所掛接table的加法操作
  • __mul: 定義乘法操作
  • __div: 定義除法操作
  • __sub: 定義減法操作
  • __mod(a, b) –取模
  • __pow(a, b) –乘冪
  • __unm: 定義負操作, 即: -table的含義
  • __concat: 定義連接操作(“..”運算符)

關系運算方法

  • __eq(a, b) –相等
  • __lt(a, b) –小于
  • __le(a, b) –小于等于

工具方法

  • __len(a) –長度
  • __tostring: 定義當table作為tostring()函式之參數被呼叫時的行為(例如: print(table)時將呼叫tostring(table)作為輸出結果)
  • __call(a, …) –執行方法調用

類似setter/getter方法

  • __index: 定義當table中不存在的key值被試圖獲取時的行為
  • __newindex: 定義在table中產生新key值時的行為

metatable操作函數

  • getmetatable
    獲取一個對象的metatable

  • setmetatable
    設置一個對象的metatable

示例

這是來自網友翻譯的lua示例

Set = {} -- 存儲對于集合的所有操作函數。 Set.mt = {} -- "metatable"。-- 創建一個新的集合。 function Set.new (t)local set = {} -- 新的集合。setmetatable(set, Set.mt) -- 所有的集合共享同一個"metatable"。-- "key-value",集合中的元素值-"true"。for _, l in ipairs(t) do set[l] = true endreturn set end-- 計算兩個集合的并集。 function Set.union (a,b)local res = Set.new{}for k in pairs(a) do res[k] = true endfor k in pairs(b) do res[k] = true endreturn res end-- 計算兩個集合的交集。 function Set.intersection (a,b)local res = Set.new{}for k in pairs(a) dores[k] = b[k] -- 很聰明的方法,如果集合"b"中沒有元素"k"的話就會返回"nil"。endreturn res end-- 我們規定"s1 - s2"相當于求"(s1 * s2)"在"s1"中的補集。 function Set.sub(a, b)local res = Set.new{}for k in pairs(a) doif not b[k] thenres[k] = trueendendreturn res end-- 我們規定"s1 / s2",僅是打印一句話,以證明調用了正確的"metamethod"。 function Set.div(a, b)local res = Set.new{"__div"}return res end-- 我們規定"-s"僅是打印一句話,以證明調用了正確的"metamethod"。 function Set.unm(a)local res = Set.new{"__unm"}return res end-- 我們規定"s1 ^ s2"僅是打印一句話,以證明調用了正確的"metamethod"。 function Set.pow(a, b)local res = Set.new{"__pow"}return res end-- 將集合轉換為字符串形式。 function Set.tostring (set)local s = "{"local sep = ""for e in pairs(set) dos = s .. sep .. esep = ", "endreturn s .. "}" end-- 打印集合。 function Set.print (s)print(Set.tostring(s)) end-- 定義meta-method Set.mt.__add = Set.union -- 定義兩個"table"相加的邏輯,并集。 Set.mt.__mul = Set.intersection -- 定義兩個"table"相乘的邏輯,交集。 Set.mt.__sub = Set.sub -- 定義兩個"table"相減的邏輯。 Set.mt.__div = Set.div -- 定義兩個"table"相除的邏輯。 Set.mt.__unm = Set.unm -- 定義一個"table"取反的邏輯。 Set.mt.__pow = Set.pow -- 定義兩個"table"相冪的邏輯。s1 = Set.new{10, 20, 30, 50} s2 = Set.new{30, 1} -- 兩個集合共享同一個"metatable"。 print(getmetatable(s1) == getmetatable(s2)) --> trueSet.print(s1 + s2) --> {1, 10, 20, 30, 50} Set.print(s1 * s2) --> {30} Set.print(s1 - s2) --> {20, 50, 10} Set.print(s1 / s2) --> {__div} Set.print(-s2) --> {__unm} Set.print(s1 ^ s2) --> {__pow}

__index metamethod控制 table 的訪問

由于metamethod __index用于訪問對象的屬性,那么我們可以修改來添加訪問控制。

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

local mt = {} function mt.__add(a, b)return 'table + ' .. b endprint ('--1--') print("mt", mt)local t = {} print("meta-table origin: ", getmetatable(t)) -- nilprint ('--2--') setmetatable(t, mt) print("meta-table", getmetatable(t)) -- tableprint(t + 1)---- ---- local mt = {} mt.__index = function(table, key) print('table -- ' .. tostring(table)) print('key -- ' .. key) return mt.key end mt.__newindex = function(table, key, value) print('table -- ' .. tostring(table)) print('key -- ' .. key) print('value -- '..value)mt.key = value; end local tt = {} setmetatable(tt, mt)print ('--3--') local v = tt.aprint("v=", v) -- nil print ('--4--') tt.a = "a" local va = mt.a; print("v-a=",va) print ('--5--') local vb= tt.b; print("v-b=",vb) print ('--6--') tt.b = "b" local vbb = tt.b print("v-b=",vb, vbb)

輸出:

--1-- mt table: 0x7ff195c04490 meta-table origin: nil --2-- meta-table table: 0x7ff195c04490 table + 1 --3-- table -- table: 0x7ff195c08550 key -- a v= nil --4-- table -- table: 0x7ff195c08550 key -- a value -- a v-a= nil --5-- table -- table: 0x7ff195c08550 key -- b v-b= a --6-- table -- table: 0x7ff195c08550 key -- b value -- b table -- table: 0x7ff195c08550 key -- b v-b= a b

總結

以上是生活随笔為你收集整理的Lua中的metatable的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。