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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Lua元表(Metatable)简易教程

發布時間:2025/3/11 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lua元表(Metatable)简易教程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 0.友情鏈接
  • 1.引言
  • 2.創建一個元表
    • 2.1.__tostring方法
    • 2.2.__add和__mul方法
    • 2.3.__index方法
    • 2.4.__call方法
  • 3.完整代碼

0.友情鏈接

  • GitHUb上下載Lua編譯器
  • Lua菜鳥教程中的元表介紹(較全,但功能性受限)
  • 博客園內元表的介紹(較詳細)
  • 簡書內元表的介紹(較簡潔)

1.引言

\qquadLua語言是用C寫的,Lua的元表類似于Python的類,但書寫難度遠比Python的Class大,加上Lua沒有免費的Debugger,這個問題就讓人很頭疼。在此寫一個可以使用多個“方法”的元表(Metatable),代碼較短,但容易理解,希望能幫到大家。
\qquad簡單理解一個Lua語言的Metatable(元表),Metatable是table的一個拓展,setmetatable是創建一個Metatable的函數,它有兩個參數——原table和Metatable的屬性、方法列表。我們從這兩方面出發創建一個Metatable。不熟悉Luatable操作的讀者,建議查看以下的簡短的教程鏈接:
Lua的table簡介

2.創建一個元表

vector = {} -- 空屬性 a = setmetatable({1,2,3},vector) -- create vector a b = setmetatable({4,5,6},vector) -- create vector b

\qquad這樣我們就創建一個空屬性的列表,對他們的操作和table是一樣的,現在我們要定義table的屬性和方法了(即vector),創建了屬性和方法的Metatable相當于繼承了table的一個Lua類,我們先從簡單的開始。

2.1.__tostring方法

\qquad__tostring方法是Metatable轉換為字符串的方法,print一個Metatable時,就查看Metatable有無此方法,若沒有,則會打印出一個table的編號;若有,則會按照此方法進行。
\qquad在此介紹一個簡單的方法,先定義一個有函數指針的Lua函數,再將這個函數指針加入vector,即完成了Metatable對__tostring方法的繼承。值得注意的是,當作為vector類的方法時,v_print函數的參數vector傳遞的參數就和python的self一樣,傳遞的是元表本身。

v_print = function(vector) -- print(v_print)return table.concat(vector,',')end vector = {v_print} a = setmetatable({1,2,3},vector) -- create vector a b = setmetatable({4,5,6},vector) -- create vector b c = {1,2,3} print(a) print(b) print(c)

運行這個Lua程序,得到的結果如下:

>lua -e "io.stdout:setvbuf 'no'" "EX5.lua" 1,2,3 4,5,6 table: 00A00920 >Exit code: 0

如果你成功了,那么恭喜你,你已經掌握了一半元表的知識。

2.2.__add和__mul方法

\qquad實際上,元表的操作方法有很多,具體就是用操作符來代替調用函數的方法,我們在此只介紹兩個——加法和乘法。按照之前的套路,先定義加法和乘法的函數,與之不同的是,加法和乘法都是雙目運算符,因此參數數目是2.

v_print = function(vec) -- print(v_print)return table.concat(vec,',')end v_add = function(vec,new_vec) -- vector_a + vector_blocal result = setmetatable({},vector)for i = 1,#new_vec doresult[i] = vec[i]+new_vec[i]endreturn resultend v_dot = function(vec,new_vec) --vector_a·vector_b (inner product)local product = 0for i,v in ipairs(vec) doproduct = product + v*new_vec[i]endreturn productend vector = {__tostring=v_print,__add=v_add,__mul=v_dot} a = setmetatable({1,2,3},vector) -- create vector a b = setmetatable({4,5,6},vector) -- create vector b print(a+b) print(a*b)

運行結果如下:

>lua -e "io.stdout:setvbuf 'no'" "Test1.lua" 5,7,9 32 >Exit code: 0

\qquad這里定義的加法,返回的仍然是Metatable類,所以打印出的結果仍然不是table的編號
其余的操作符方法類似,在此不再贅述

模式描述
__adda+b
__suba-b
__mula*b
__diva/b
__moda%b
__unm-a
__concat..\text{..}..
_eqa==b
__lta<b
__lea<=b

2.3.__index方法

\qquad官方文檔對于__index方法的解釋是,若在元表中未找到對應的key(鍵值),則調用__index方法查找,文字敘述較為生疏,下面是一個例子:

v_print = function(vec) -- print(v_print)return table.concat(vec,',')end v_sum = function(vec) -- sum of a veclocal sum = 0for i,v in ipairs(vec) dosum = sum+vendreturn sumend v_index = function(vec,value) -- value method of a vecif value == "sum" thenreturn v_sum(vec)endend vector = {__index = v_index,__tostring = v_print} a = setmetatable({1,2,3},vector) -- create vec a print(a) print(a["sum"])

輸出結果如下

>lua -e "io.stdout:setvbuf 'no'" "Test2.lua" 1,2,3 6 >Exit code: 0

\qquad可以發現,元表a中并沒有"sum"這個鍵,所有程序調用__index方法,成功找到了鍵"sum"對應的value(這里是一個函數返回的值)。但是值得注意的是,這個方法并不支持多參數的傳入,如果需要,請看下文。

2.4.__call方法

\qquad__call方法容許元表像函數用于使用,類似像a(para1,para2)的形式,和前面的方法一樣,第一個參數默認傳遞的是a本身,但在調用的時候省略(與python的方法調用一致)。還是一樣,先看一段簡短的程序加深理解。

v_call = function(vec,new_vec,value) -- vec(...)if value == nil thenfor i,v in ipairs(new_vec) dovec[i] = vendreturn vecendif value == "mul" thenreturn v_mul(vec,new_vec)endend v_print = function(vec) -- print(v_print)return table.concat(vec,',')end v_mul = function(vec,new_vec) -- vec_a.*vec_b (dot multiply)local result = setmetatable({},vector)for i,v in ipairs(vec) doresult[i] = v*new_vec[i]endreturn resultend vector = {__tostring=v_print,__call=v_call} a = setmetatable({1,2,3},vector) -- create vector a b = setmetatable({4,5,6},vector) -- create vector b print(a) print(b) print(a(b,"mul"))

輸出結果:

>lua -e "io.stdout:setvbuf 'no'" "Test3.lua" 1,2,3 4,5,6 4,10,18 >Exit code: 0

\qquad我們使用__call方法串入了兩個參數,一個是Metatable b,還有一個是方法“mul”,雖然他是字符串,但在v_call中,它表示調用了v_mul方法。

3.完整代碼

\qquad在此附上完整的代碼及輸出結果,方便讀者對照理解。

v_add = function(vec,new_vec) -- vec_a + vec_blocal result = setmetatable({},vec)for i = 1,#new_vec doresult[i] = vec[i]+new_vec[i]endreturn resultend v_call = function(vec,new_vec,value) -- vec(...)if value == nil thenfor i,v in ipairs(new_vec) dovec[i] = vendreturn vecendif value == "mul" thenreturn v_mul(vec,new_vec)endend v_print = function(vec) -- print(v_print)return table.concat(vec,',')end v_mul = function(vec,new_vec) -- vec_a.*vec_b (dot multiply)local result = setmetatable({},vector)for i,v in ipairs(vec) doresult[i] = v*new_vec[i]endreturn resultend v_dot = function(vec,new_vec) --vec_a·vec_b (inner product)local product = 0for i,v in ipairs(vec) doproduct = product + v*new_vec[i]endreturn productend v_sum = function(vec) -- sum of a veclocal sum = 0for i,v in ipairs(vec) dosum = sum+vendreturn sumend v_index = function(vec,value) -- value method of a vecif value == "sum" thenreturn v_sum(vec)endend vector = {__add=v_add,__call = v_call,__tostring=v_print,__mul=v_dot,__index=v_index} a = setmetatable({1,2,3},vector) -- create vec a b = setmetatable({4,5,6},vector) -- create vec b print(a) print(b) print(table.concat(a+b,",")) print(a*b) print(a["sum"]) print(a(b,"mul"))

輸出結果:

>lua -e "io.stdout:setvbuf 'no'" "EX5.lua" 1,2,3 4,5,6 5,7,9 32 6 4,10,18 >Exit code: 0

希望本文對您有幫助,感謝您的閱讀。

總結

以上是生活随笔為你收集整理的Lua元表(Metatable)简易教程的全部內容,希望文章能夠幫你解決所遇到的問題。

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