元表
元表的定義
允許我們改變table的行為。
setmetatable(普通表,元表)-- 元表a?= {"a","b","c"}?-- 普通表?b?=?{}?--元表c?= setmetatable(a,b)print("------------------------")f?=?{}print("f:",f)d?= setmetatable({"c","d"},f)print(d[1])e?= getmetatable(d)print("e:",e)
index元方法
__index?(兩個下劃線)定義普通表?p。給普通表p,設置元表y,而元表y中有__index,__index=一個表 i,i中有 我們訪問的那個不存在的?key。__index=表print("-------------測試__index---------------")?-- 普通表tab1?= {"a","b","c"}print(tab1[5])-- 普通表,有一個元素?5="e"?newTab?=?{}newTab[5]?=?"e"metaTab1?= {__index=newTab}setmetatable(tab1,?metaTab1)print(tab1[5])--index=函數(表,key)-- 普通表tab1?= {"a","b","c"} print(tab1[5])print("原始的tab1:",tab1)metaTab1?=?{__index=function(tab,?key?)print("參數當中的tab:",tab)print("參數當中的key:",key)if(key?==?5) thenreturn?"index--5"?endend}setmetatable(tab1,?metaTab1)print(tab1[5])請求表中key的值:先在普通表中找,有返回,沒有,看元表。如果元表有__index, 且 __index中有對應的key。?如果沒有,繼續找__index的function。
newindex元方法
對表進行更新時調用。函數用法print("-----------newindex--------------")?mytab2?= {"a","b"}metatab2?=?{__newindex?= function(tab,?key?,value)print("被調用")-- tab[key]?= valuerawset(tab,key,value)end}setmetatable(mytab2,metatab2)mytab2[3]="c"print(mytab2[3])表mytab2?= {"a","b"}mytab21?=?{}?metatab2?=?{__newindex?=?mytab21}setmetatable(mytab2,metatab2)mytab2[3]="c"print(mytab2[3])print(mytab2[3])
為表添加操作符
加法操作print("-------------操作符------------")?tab3?= {"1","2"}tab4?= {"a","b","c"}metatab3?=?{__add?= function(tab1,tab2)?local?m?= #tab1for?k,v?in?pairs(tab2)dom?=?m+1tab1[m]?= vendreturn?tab1end}setmetatable(tab3,metatab3)v?= tab3?+?tab4?print(v)for?k,v?in?pairs(v)?doprint(k,v)?end__add:+?__sub:?-?_mul:*???__div: /__mod:?%__concat:?..__eq:==?__lt:?<_le:?<=
call元方法
lua中,當表被當成函數調用時,會觸發。print("-----------call-------------")?tab_a1?= {"a","b"}print("tab_a1原始值:",tab_a1)?tab_a2?= {"1","2"}metatab_a?=?{__call?= function(tab, ...)local?a?=?{...}for?k,v?in?pairs(a) doprint(v)endend}setmetatable(tab_a1,metatab_a)result?= tab_a1(6,7,8)
tostring
用于修改表的輸出行為。類似于java中的toString()。print("-----------call-------------")?tab_a1?= {"a","b","c","d"}print("tab_a1原始值:",tab_a1)?tab_a2?= {"1","2"}metatab_a?=?{__call?= function(tab, ...)local?a?=?{...}for?k,v?in?pairs(a) doprint(v)endend,__tostring?= function(tab)local?str?=?""for?k,v?in?pairs(tab) dostr?=?str..v..","return?str?end}setmetatable(tab_a1,metatab_a) --?result?= tab_a1(6,7,8)print(tab_a1)ps:每個元方法之間 用 ,
協同程序
類似于 多線程的概念。
協程和線程的區別:
一個多線程的程序,可以同時運行多個線程。而協程呢,在某個時刻,只有一個協程在運行。?線程由cpu調度,協程由代碼調度。
創建協程,并運行:
# 定義協程testAdd?= coroutine.create(?function(a,b)print(a+b)end)# 啟動協程# 原來暫停-》執行,原來執行-》暫停?coroutine.resume(testAdd,?1,2)wrapco?= coroutine.wrap(function(a)print("參數值是:"..a)end)co(2)
啟動、停止
testAdd?= coroutine.create(function(a,b)print("執行--子方法",a+b)coroutine.yield();print("執行--子方法",a-b)end)coroutine.resume(testAdd,?1,7)print("執行主方法")coroutine.resume(testAdd)
返回值
testAdd?= coroutine.create(function(a,b)print("協程執行",a+b)coroutine.yield()return?a+b,a-b?end)r1,r2,r3?= coroutine.resume(testAdd,?1,7)print("返回值:",r1,r2,r3)r1,r2,r3?= coroutine.resume(testAdd,?1,7)print("重新執行,返回值:",r1,r2,r3)
協程狀態
testAdd?= coroutine.create(function(a,b)print("運行中 協程狀態:",coroutine.status(testAdd))?coroutine.yield()return?a+b,a-b?end)print("剛定義好的協程狀態:",coroutine.status(testAdd))r1?= coroutine.resume(testAdd,1,4)print("啟動協程結果:",r1)print("最終的 協程狀態:",coroutine.status(testAdd))print("yield后 協程狀態:",coroutine.status(testAdd))r1?= coroutine.resume(testAdd,1,4)print("二啟動協程結果:",r1)print("二最終的 協程狀態:",coroutine.status(testAdd))r1?= coroutine.resume(testAdd,1,4)print("三啟動協程結果:",r1)結果:剛定義好的協程狀態:????suspended運行中 協程狀態:???????running啟動協程結果:??true最終的 協程狀態:???????suspendedyield后 協程狀態:??????suspended二啟動協程結果:????????true二最終的 協程狀態:?????dead三啟動協程結果:????????false
協程協作
協程唯一標識testAdd?= coroutine.create(function(a,b)print(coroutine.running)print("1")?end)coroutine.resume(testAdd,1,1)協程內部和外部協作的例子:-- 協程內外部協作的例子?function?foo(a)print("foo?參數:",a)return?coroutine.yield(a*2)?endco?= coroutine.create(function(a,b)print("第一次啟動協程,參數:",a,b)?local?r?= foo(a+1)print("第二次啟動協程,參數",r)local?x,y?= coroutine.yield(a+b,a-b)print("第三次啟動協程,參數",x,y)return?b,"協程結束啦"end)print("主程序:",coroutine.resume(co,1,5))print("----分隔符---")print("主程序:",coroutine.resume(co,"r"))print("----分隔符---")print("主程序:",coroutine.resume(co,"x","y"))print("----分隔符---")print("主程序:",coroutine.resume(co))第一次resume,傳入的參數是 function的參數。第一次yield的參數,是第一次resume的返回值。第二次resume的參數,是第一次yield的 返回值。
生產者消費者問題
思路:1。生產者生產完 產品,(自己停下來),等待消費者消費。2。消費者消費完產品,(自己停下來),等待生產者生產。-- 生產者和消費者function?productor()-- 定義生產的商品,用數字來替代?local?i?=?0while?i<100doi?=?i+1print("生產了:",i)-- 通過協程實現coroutine.yield(i)?endendfunction?consumer()?while?truedo-- 從生產者獲取產品local?status,result?= coroutine.resume(po)?print("消費了:",result)if (result?==?99)?thenbreakendendend-- 程序開始po?= coroutine.create(productor)consumer()