国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Lua學習筆記】Lua進階——Table(3) 元表

這篇具有很好參考價值的文章主要介紹了【Lua學習筆記】Lua進階——Table(3) 元表。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【Lua學習筆記】Lua進階——Table(3) 元表,Lua學習筆記,lua,學習,筆記
接上文


元表

Q:為什么要使用元表?

A:在Lua中,常常會需要表與表之間的操作。元表中提供了一些元方法,通過自定義元方法可以實現(xiàn)想要的功能,相當于面向?qū)ο笾薪o你一系列方法讓你重載。

使用下列代碼設置元表:

meta={}
table={}
setmetatable(table,meta) -- 第一個元素為子表,第二個元素為元表

通常在元表中操作分為三步:

  1. 操作子表
  2. 檢測是否有元表
  3. 若有元表,檢測有無對應元方法,沒有元方法則返回對應操作本來的處理。若有對應元方法執(zhí)行元方法。

元方法索引一般以"__"(兩個下劃線,我想這是因為命名私有靜態(tài)變量常常以一個下劃線作為開頭)作為開頭,例如下面的例子:

__tostring

meta = {}
table={}
setmetatable(table, meta)
print(table)
輸出:
table: 00ABA2A8
meta = {
    __tostring = function ()  <--注意兩個下劃線
        return "123"
    end
}
table={}
setmetatable(table, meta)
print(table)

輸出:
123

上例相當于使用元方法重載print函數(shù)

meta = {
    __tostring = function (t)
        return t.name
    end
}
table={name = "233"}
setmetatable(table, meta)
print(table)

輸出:
233

在上例中,即使我們未指定元方法的入?yún)?,但是因為子表和元表的關(guān)聯(lián),元方法會自動地將子表作為參數(shù)傳入元方法。


__call

讓我們再定義一個__call元方法

meta = {
    __tostring = function ()
        return "456"
    end,
    __call = function(a)
        print(a.name)
        print(a)
        print("call")
    end
}
table={name = "123"}
setmetatable(table, meta)
table(2)  --無論table(x)中給出的x為幾,結(jié)果都是一樣的

輸出:
123
456
call

定義了__call元方法后,我們使用table(index),發(fā)現(xiàn)__call元方法打印了123,456和call,123是子表的元素,而456是__tostring的返回結(jié)果。這意味著__call方法調(diào)用了子表作為入?yún)。并且像我們上面的打印樣例一樣,print(a)方法又同時會調(diào)用__tostring的元方法。而table(2)中的參數(shù)2很明顯被無視了。

現(xiàn)在我們可以確定一個基本規(guī)則:當使用__tostring__call元方法時,我們定義的第一個參數(shù)一定是子表table本身,只有定義更多參數(shù)才能接收其它入?yún)ⅲ?/strong>

meta = {
    __tostring = function ()
        return "456"
    end,
    __call = function(a,b)
        print(a)
        print(b)
        print("call")
    end
}
table={name = "123"}
setmetatable(table, meta)
table(2)

輸出:
456
2
call

__index

meta = {
}
table1 = { age = 1 }
setmetatable(table1, meta)
print(table1.name)

輸出:
nil

我們想要找到表中的name索引,當然是沒有的,輸出結(jié)果是nil
那能不能讓元表擁有這個索引呢?答案是不行,因為找的還是table1:

meta = {name =1}
table1 = { age = 1 }
setmetatable(table1, meta)
print(table1.name)

輸出:
nil

現(xiàn)在我們定義一個元方法 __index,它會指向一個其他的查詢表

meta = { name = 2 }
meta.__index = meta
table1 = { age = 1 }
setmetatable(table1, meta)
print(table1.name)

輸出:
2

整個查找的流程其實是:

  1. 查詢子表
  2. 子表查詢失敗,查詢元表有無 __index元方法
  3. 若有,則查詢 __index元方法指向的表

但是還有種情況,建議不要把__index元方法在元表內(nèi)部定義:

meta = {
    name = 2,
    __index = meta,
}
table1 = { age = 1 }
setmetatable(table1, meta)
print(table1.name)


輸出:
nil   --不明覺厲

還可以套娃

meta = {
}
metaFather = {
    name =4,
}
table1 ={age =1}
meta.__index = meta  --讓元表的index指向meta,子表找不到就去meta里找
metaFather.__index =metaFather --讓元表的index指向metaFather,子表找不到就去metaFather里找
setmetatable(meta,metaFather)
setmetatable(table1, meta)
print(table1.name)

輸出:i
4  --允許套娃

__newindex

看4個例子:

meta = {}
table1 ={}
table1.age = 1
setmetatable(table1, meta)
print(table1.age)

輸出:
1

meta = {}
table1 ={age = 1}
meta.__newindex = {}
setmetatable(table1, meta)
print(table1.age)

輸出:
1

meta = {}
table1 ={}
meta.__newindex = {}
setmetatable(table1, meta)
table1.age = 1
print(table1.age)

輸出:
nil

meta = {}
table1 ={}
meta.__newindex = {}
table1.age = 1
setmetatable(table1, meta)
print(table1.age)

輸出:
1

有沒有很詭異?其實很好理解,這是由于__newindex元方法,它的作用其實是將子表新加入的元素加入到__newindex所指向的表而不修改子表(當然__newindex也可以套娃):

meta = {}
table1 ={}
meta.__newindex = {}
setmetatable(table1, meta)
table1.age =1
print(table1.age)
print(meta.__newindex.age)

輸出:
nil
1


運算符元方法

meta = {
    __sub = function (t1,t2)
        return t1.age - t2.age
    end
}
table1={age=1}
table2={age=2}
setmetatable(table1, meta)  --無論把元表設置給table1還是table2,結(jié)果都一樣
print(table1 - table2)

輸出:
-1

我們發(fā)現(xiàn)使用運算符元方法的時候,第一個參數(shù)也不默認是綁定的子表了。而是根據(jù)運算符的左右變量依次給元方法賦值。而且無論元表設置給減數(shù)還是被減數(shù),最終結(jié)果都是不變的。運算符元方法較多,這里就不詳細列舉了,從菜鳥教程上直接抄了個表格:

元方法 描述
__add 對應的運算符 ‘+’
__sub 對應的運算符 ‘-’
__mul 對應的運算符 ‘*’
__div 對應的運算符 ‘/’
__mod 對應的運算符 ‘%’
__unm 對應的運算符 ‘-’
__concat 對應的運算符 ‘..’
__pow 對應的運算符 ‘^’
__eq 對應的運算符 ‘==’
__lt 對應的運算符 ‘<’
__le 對應的運算符 ‘<=’

在這之中除了正常的數(shù)學運算,我們還需要講一下比較特殊的邏輯判斷的元方法(就是上表中加粗的幾列),這幾個元方法需要運算符的雙方都綁定同一個元表。原因是元方法沒有提供大于符號,運算a>b的元方法其實相當于運算b<a的原方法,這就需要b也綁定元表,因此邏輯運算硬性要求運算雙方都綁定同一個元表,讓我們看看下列的例子:

meta = {
    __eq= function (t1,t2)
        return true
    end,
}
table1 = { age = 1 }
table2 = { name = nil }
setmetatable(table1, meta)
print(table1 == table2)
setmetatable(table2, meta)
print(table1 == table2)

輸出:
false
true

我們可以發(fā)現(xiàn)上述的相等的邏輯判斷是有問題的,第一個print出false,第二個print出true。

在第一個print的時候,只有table1綁定了元表,而table2沒有,之所以return false是因為在邏輯運算的時候需要左右雙方都綁定同一個元表。

而在第二個print的時候打印了true,即使table1table2內(nèi)容不同。因為這是我們自定義的元方法,我們默認返回的就是true。

幾道例題,請思考下列幾個例子的輸出結(jié)果:

meta = {
    __eq= function (t1,t2)
        if t1.age == t2.age then
            return true
        end
    end,
}
table1 = { age = 1 }
table2 = { age = 2 }
setmetatable(table1, meta)
setmetatable(table2, meta)
print(table1 == table2)

輸出:
false

上述例子中,我們用__eq元方法來判斷age索引值是否相同,顯然是不同的,因此是false

meta = {
    __eq= function (t1,t2)
        if t1.name == t2.name then
            return true
        end
    end,
}
table1 = { age = 1 }
table2 = { name = nil }
setmetatable(table1, meta)
setmetatable(table2, meta)
print(table1 == table2)

輸出:
true

上述例子中,我們用元方法判斷name索引值是否相同,而table1沒有name索引,默認為nil,table2有name = nil,因此是true

meta = {
    __eq= function (t1,t2)
        if t1 == t2 then
            return true
        end
    end,
}
table1 = { age = 1 }
table2 = { name = nil }
setmetatable(table1, meta)
setmetatable(table2, meta)
print(table1 == table2)

輸出:
棧溢出

上述例子中,我們在元方法內(nèi)部判斷t1==t2,而進行判斷時相當于再次調(diào)用了__eq元方法,因此會無限循環(huán)最終導致棧溢出。文章來源地址http://www.zghlxwxcb.cn/news/detail-617369.html


其它元表操作

print(getmetatable(table1)) --使用getmetatable方法獲得table1的元表地址

輸出:
table: 00BBA320
meta = { name = 2 }
meta.__index = meta
table1 = { age = 1 }
setmetatable(table1, meta)
print(rawget(table1,"nane"))  --rawget方法只查詢子表,無視元表index

輸出:
nil
meta = {}
table1 ={}
meta.__newindex = {}
setmetatable(table1, meta)
table1.age =1
print(table1.age)
rawset(table1, "age", 1) --rawset方法可以無視元表的newindex,直接修改子表
print(table1.age)

輸出:
nil
1

到了這里,關(guān)于【Lua學習筆記】Lua進階——Table(3) 元表的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • 【Lua學習筆記】Lua進階——函數(shù)和閉包

    【Lua學習筆記】Lua進階——函數(shù)和閉包

    使用函數(shù)嵌套的用法,我們可以將另一個函數(shù)作為返回值,但是返回函數(shù)作為一個值是要被賦值給其他變量的,所以return時不能起名(賦值)為其他變量名。 推薦閱讀深入Lua:函數(shù)和閉包 在函數(shù)嵌套中,我們需要接觸一個叫做閉包的概念 這就是一個閉包,它由一個函數(shù)和該

    2024年02月15日
    瀏覽(26)
  • Lua學習筆記:淺談table的實現(xiàn)

    Lua學習筆記:淺談table的實現(xiàn)

    前言 本篇在講什么 Lua中的table的實現(xiàn) 本篇適合什么 適合 初學Lua 的小白 本篇需要什么 對 Lua 語法有簡單認知 依賴 Sublime Text 編輯器 本篇的特色 具有全流程的 圖文教學 重實踐,輕理論,快速上手 提供全流程的 源碼 內(nèi)容 ★提高閱讀體驗★ ?? ? 三級標題 ?? ?? ? 四級標

    2024年02月12日
    瀏覽(23)
  • 【Lua學習筆記】Lua進階——Require,三目運算

    【Lua學習筆記】Lua進階——Require,三目運算

    這是文件 aaa.lua 的內(nèi)容 這是文件 example.lua 的內(nèi)容 可以看到,在使用require之后,會直接對其他文件進行調(diào)用執(zhí)行。而且我們可以直接訪問它的全局變量,并且發(fā)現(xiàn)我們的全局變量被覆蓋了,而它的局部變量就像private一樣,不能被這個文件訪問。 從 package.loaded 這個方法我們可

    2024年02月15日
    瀏覽(28)
  • lua的元表與元方法理解

    lua的元表與元方法理解

    在 Lua 中,元表(metatable)是一種特殊的表,用于定義另一個表的行為。每個表都有一個關(guān)聯(lián)的元表,通過元表可以重載表的各種操作,例如索引、新索引、相加等。在 Lua 中,元表的使用非常靈活,可以實現(xiàn)各種高級特性,例如面向?qū)ο缶幊?、迭代器等?元表與表的關(guān)聯(lián)是

    2024年02月10日
    瀏覽(24)
  • Lua 進階 · 教程筆記

    Lua 進階 · 教程筆記

    筆記的內(nèi)容出自 Bilibili 上的視頻:Lua教程-進階部分 - 4K超清【不定期更新】 筆記主要用于供筆者個人或讀者回顧知識點,如有紕漏,煩請指出 : ) 國內(nèi)的大佬 云風 翻譯了 Lua 的 Api 參考手冊:傳送門【】 以后讀者在練習或者開發(fā)途中可以在參考手冊里查看 Lua 提供的 Api。

    2024年01月24日
    瀏覽(97)
  • 【Lua學習筆記】Lua入門

    【Lua學習筆記】Lua入門

    (不是教程,推薦有編程基礎(chǔ)的人觀看本文) 文中主要包含了對菜鳥教程中的一些學習理解,個人感覺Lua語言和Python很多地方相似 以下大部分代碼和表格摘抄自菜鳥教程 數(shù)據(jù)類型 描述 nil 只有值nil屬于該類,表示一個無效值(在條件表達式中相當于false)(類似與Null或者

    2024年02月15日
    瀏覽(27)
  • lua學習筆記21完結(jié)篇(lua中的垃圾回收)

    lua學習筆記21完結(jié)篇(lua中的垃圾回收)

    輸出 學習地址? 【唐老獅】Unity熱更新之Lua語法_嗶哩嗶哩_bilibili?

    2024年04月15日
    瀏覽(44)
  • Lua學習筆記:require非.lua拓展名的文件

    Lua學習筆記:require非.lua拓展名的文件

    前言 本篇在講什么 Lua的require相關(guān)的內(nèi)容 本篇需要什么 對 Lua 語法有簡單認知 對 C++ 語法有簡單認知 依賴 Visual Studio 工具 本篇的特色 具有全流程的 圖文教學 重實踐,輕理論,快速上手 提供全流程的 源碼 內(nèi)容 ★提高閱讀體驗★ ?? ? 三級標題 ?? ?? ? 四級標題 ?? 想

    2024年02月07日
    瀏覽(21)
  • lua學習筆記

    lua學習筆記

    單行注釋: 多行注釋: 命名: Lua不支持下劃線+大寫字母,比如:_ABC 但支持:_abc : 全局變量: 直接變量名 = 內(nèi)容就是全局 局部變量: 加上local即可 nil: nil是空的意思,即什么也沒有 lua的數(shù)據(jù)類型: table: lua從下表為1開始的 if else elseif: nil默認為false ..: ..為字

    2024年02月07日
    瀏覽(23)
  • lua腳本語言學習筆記

    lua腳本語言學習筆記

    Lua 是一種輕量小巧的腳本語言,用標準C語言編寫并以源代碼形式開放, 其設計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能。 因為我們使用redis的時候一般要寫lua腳本,這篇文章就介紹一下lua腳本語言的基礎(chǔ)用法。 window操作系統(tǒng)下可以使用SciTE來

    2024年02月16日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包