一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語(yǔ)言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Lua - Lua中的__index和__newindex實(shí)例

Lua中的__index和__newindex實(shí)例

2020-04-14 10:45果凍想 Lua

這篇文章主要介紹了Lua中的__index和__newindex實(shí)例,本文講解了具有默認(rèn)值的table、記錄table的訪問(wèn)、只讀的table等內(nèi)容,需要的朋友可以參考下

前言

這篇博文將通過(guò)幾個(gè)簡(jiǎn)單的實(shí)例演示,鞏固對(duì)__index和__newindex的理解,同時(shí)加深對(duì)Lua中元表和元方法的理解,如果對(duì)Lua的元表和元方法還不是很熟悉的話,請(qǐng)參考這篇文章:《Lua中的元表與元方法》。

具有默認(rèn)值的table

我們都知道,table中的任何字段的默認(rèn)值都是nil,但是通過(guò)元表,我們可以很容易的修改這一規(guī)定,代碼如下:

 

復(fù)制代碼 代碼如下:

function setDefault(tb, defaultValue)
     local mt = {__index = function () return defaultValue end}
     setmetatable(tb, mt)
end
 
local tb1 = {x = 10, y = 20}
print(tb1.x, tb1.z)     --> 10 nil
setDefault(tb1, 100) -->設(shè)置默認(rèn)值
print(tb1.x, tb1.z) --> 10 100 這里打印的就是默認(rèn)值


可以看到,在代碼中,setDefault函數(shù)為所有需要默認(rèn)值的table創(chuàng)建了一個(gè)新的元表。如果準(zhǔn)備創(chuàng)建很多需要默認(rèn)值得table,這種方法的開(kāi)銷或許就比較大了。由于在元表中默認(rèn)值defaultValue是與元方法關(guān)聯(lián)在一起的,所以setDefault無(wú)法為所有table都使用同一個(gè)元表。如果要讓具有不同默認(rèn)值得table都使用同一個(gè)元表,那么就需要將每個(gè)元表的默認(rèn)值存放在table本身中,可以使用一個(gè)額外的字段來(lái)存儲(chǔ)默認(rèn)值。例如以下代碼:

 

 

復(fù)制代碼 代碼如下:

local mt = {__index = function (t) return t.___ end}
function setDefault(tb, defaultValue)
     tb.___ = defaultValue       -- 非常謝謝hellowei犀利的review。具體請(qǐng)參見(jiàn)評(píng)論
     setmetatable(tb, mt)
end


上面代碼中的“___”是為了防止名字沖突而起的名字;如果這樣的話,你還擔(dān)心名字沖突,確保key在table中的唯一性,只需要?jiǎng)?chuàng)建一個(gè)新的table,并用它作為key即可,每一個(gè)新創(chuàng)建的table都是一個(gè)唯一的地址,比如以下代碼:

 

 

復(fù)制代碼 代碼如下:

local key = {} -- 唯一的key
local mt = {__index = function (tb) return tb[key] end}
 
function setDefault(tb, defaultValue)
     tb[key] = defaultValue
     setmetatable(tb, mt)
end

 

記錄table的訪問(wèn)

有的時(shí)候,一種特定的需求,我們需要記錄對(duì)一個(gè)table的所有訪問(wèn),不管是查詢還是更新,我們都需要記錄日志。這如何完成?我們都知道,元表中的__index和__newindex是在table中沒(méi)有所需要訪問(wèn)的index時(shí)才發(fā)揮作用的,因此,只有將一個(gè)table保持為空,然后設(shè)置__index和__newindex元方法,才有可能記錄下來(lái)所有對(duì)它的訪問(wèn)。

為了監(jiān)視一個(gè)table的所有訪問(wèn),就應(yīng)該為真正的table創(chuàng)建一個(gè)代理。這個(gè)代理就是一個(gè)空的table,其中__index和__newindex元方法可用于跟蹤所有的訪問(wèn),并將訪問(wèn)重定義到原來(lái)的table上。這就是思路,接下來(lái)看代碼:

 

復(fù)制代碼 代碼如下:

local t = {} --原來(lái)的table
 
-- 保持對(duì)原table的一個(gè)引用
local _t = t
 
-- 創(chuàng)建代理
t = {}
 
-- 創(chuàng)建元表
local mt = {
__index = function (t, k)
print("access to element " .. tostring(k))
return _t[k]
end,
 
__newindex = function (t, k, v)
print("update of element " .. tostring(k))
_t[k] = v
end
}
 
setmetatable(t, mt)
 
t.x = 10 -- update of element x
print(t.x) -- access to element x


如果想要同時(shí)監(jiān)視幾個(gè)table,無(wú)須為每個(gè)table創(chuàng)建不同的元表;相反,只要以某種形式將每個(gè)代理與其原table關(guān)聯(lián)起來(lái),并且所有代理都共享一個(gè)公共的元表。這個(gè)問(wèn)題與設(shè)置table默認(rèn)值相關(guān)聯(lián)的問(wèn)題類似,也是將原來(lái)的table保存在代理table的一個(gè)特殊的字段中。代碼如下:

 

 

復(fù)制代碼 代碼如下:

-- 創(chuàng)建唯一索引
local index = {}
 
-- 創(chuàng)建元表
local mt = {
     __index = function (t, k)
          print("access to element " .. tostring(k))
          return t[index][k]
     end,
 
     __newindex = function (t, k, v)
          print("update of element " .. tostring(k))
          t[index][k] = v
     end
}
 
function track(t)
     local proxy = {}
     proxy[index] = t
     setmetatable(proxy, mt)
     return proxy
end
 
local t = {}
local proxy = track(t)
proxy.x = 10
print(proxy.x)

 

只讀的table

通過(guò)代理的概念,可以很容易的實(shí)現(xiàn)只讀的table。只需要跟蹤所有對(duì)table的更新操作,并引發(fā)一個(gè)錯(cuò)誤就好了,對(duì)于查詢時(shí),我們不用去館,只需要管對(duì)table的更新操作,廢話不說(shuō),來(lái)段簡(jiǎn)單的代碼,自然而然的一目了然了。

復(fù)制代碼 代碼如下:

function readOnly(t)
     local proxy = {}
 
     -- 創(chuàng)建元表
     local mt = {
          __index = t,
          __newindex = function (t, k, v)
               error("Attempt to update a read-only table", 2)
          end
     }
 
     setmetatable(proxy, mt)
     return proxy
end
 
local tbDemo = readOnly{1, 2, 3, 4, 5}
print(tbDemo[1])
tbDemo[1] = 20


元表中__index對(duì)應(yīng)的是原來(lái)的table,而更新原來(lái)的table時(shí),就會(huì)顯示錯(cuò)誤提示:Attempt to update a read-only table。

 

總結(jié)

這篇文章對(duì)Lua中的__index和__newindex的使用進(jìn)行了詳細(xì)的講解和分析,并提供了實(shí)際的代碼,主要是為了加深對(duì)Lua中元表和元方法的理解,元表和元方法在Lua中的地位太總要了,很多高級(jí)的編程技巧和特殊需求都是基于元表和元方法來(lái)實(shí)現(xiàn)了,所以,也希望大家能好好的閱讀這篇文章,同時(shí)也希望我的文章對(duì)大家有幫助。

延伸 · 閱讀

精彩推薦
  • Lua深入探究Lua中的解析表達(dá)式

    深入探究Lua中的解析表達(dá)式

    這篇文章主要介紹了深入探究Lua中的解析表達(dá)式,對(duì)于其語(yǔ)法部分的說(shuō)明和示例都超詳細(xì),極力推薦此文!需要的朋友可以參考下 ...

    腳本之家3542020-05-05
  • LuaLua實(shí)現(xiàn)__add方法重載示例

    Lua實(shí)現(xiàn)__add方法重載示例

    這篇文章主要介紹了Lua實(shí)現(xiàn)__add方法重載示例,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下 ...

    腳本之家7452020-04-24
  • LuaLua中的元方法__newindex詳解

    Lua中的元方法__newindex詳解

    這篇文章主要介紹了Lua中的元方法__newindex詳解,本文講解了查詢與更新、監(jiān)控賦值、通過(guò)table給另一個(gè)table賦值等內(nèi)容,需要的朋友可以參考下 ...

    笨木頭8872020-04-09
  • LuaLua中table庫(kù)函數(shù)方法介紹

    Lua中table庫(kù)函數(shù)方法介紹

    這篇文章主要介紹了Lua中table庫(kù)函數(shù)方法介紹,本文講解了concat、insert、maxn、remove、sort、foreachi等方法,需要的朋友可以參考下 ...

    腳本之家2502020-04-17
  • LuaLua中計(jì)算、執(zhí)行字符串中Lua代碼的方法

    Lua中計(jì)算、執(zhí)行字符串中Lua代碼的方法

    這篇文章主要介紹了Lua中計(jì)算、執(zhí)行字符串中Lua代碼的方法,類似JavaScript中eval函數(shù)的功能,在Lua中也可以實(shí)現(xiàn),需要的朋友可以參考下 ...

    腳本之家6322020-04-30
  • LuaLua簡(jiǎn)介、編譯安裝教程及變量等語(yǔ)法介紹

    Lua簡(jiǎn)介、編譯安裝教程及變量等語(yǔ)法介紹

    這篇文章主要介紹了Lua簡(jiǎn)介、編譯安裝教程及變量等語(yǔ)法介紹,本文同時(shí)講解了lua注釋語(yǔ)法、Lua命令行方式等內(nèi)容,需要的朋友可以參考下 ...

    junjie3632020-04-14
  • LuaLua教程(二):基礎(chǔ)知識(shí)、類型與值介紹

    Lua教程(二):基礎(chǔ)知識(shí)、類型與值介紹

    這篇文章主要介紹了Lua教程(二):基礎(chǔ)知識(shí)、類型與值介紹,本文講解了Hello World程序、代碼規(guī)范、全局變量、類型與值等內(nèi)容,需要的朋友可以參考下 ...

    腳本之家5922020-04-28
  • LuaLua和C語(yǔ)言的交互詳解

    Lua和C語(yǔ)言的交互詳解

    這篇文章主要介紹了Lua和C語(yǔ)言的交互詳解,Lua和C語(yǔ)言通過(guò)棧完成交互,本文結(jié)合代碼實(shí)例詳細(xì)講解了交互的方法,需要的朋友可以參考下 ...

    果凍想3702020-04-14
主站蜘蛛池模板: 好男人好资源在线观看 | 色图片小说 | 亚洲男人天堂网站 | 亚洲午夜精品久久久久久人妖 | 国产偷窥女洗浴在线观看亚洲 | 黑帮少爷爱上我第8集最新 荷兰精品女人性hd 和日本免费不卡在线v | 国产精品视频久久久 | 亚洲精品一区二区三区在线看 | 亚洲无人区乱码中文字幕 | 欧美一级特黄特色大片免费 | 欧美人禽杂交av片 | 手机av影院| 亚洲成人在线播放 | 日韩在线第一区 | 四虎成人免费大片在线 | 亚洲精品成人在线 | 桃色公寓 | 黄网在线观看免费网站台湾swag | narutotsunade全彩雏田 | 美女脱了内裤让男生玩屁股 | gay小太正初精 | 亚洲 综合 欧美在线 热 | 俺去俺来也www色官网免费的 | 67194在线免费观看 | 护士让我吃奶我扒她奶 | 免费一区在线观看 | 日本艳鉧动漫1~6完整版在 | 插入影院| 日韩欧美一区二区三区免费看 | 亚洲成人一区在线 | 久99久热只有精品国产99 | 免费xxxx日本大片在线观看 | 日韩精品一区二区三区老鸭窝 | 我要看靠逼片 | 蜜桃破解版免费看nba | 午夜爱 | 侵犯小男生免费视频网站 | 日本大尺度激情做爰叫床 | 亚洲成人77777 | 欧美一区二区三区精品 | 调教车文 |