最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Lua中的__index和__newindex實例

 更新時間:2014年09月29日 10:37:15   作者:果凍想  
這篇文章主要介紹了Lua中的__index和__newindex實例,本文講解了具有默認值的table、記錄table的訪問、只讀的table等內(nèi)容,需要的朋友可以參考下

前言

這篇博文將通過幾個簡單的實例演示,鞏固對__index和__newindex的理解,同時加深對Lua中元表和元方法的理解,如果對Lua的元表和元方法還不是很熟悉的話,請參考這篇文章:《Lua中的元表與元方法》。

具有默認值的table

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

復制代碼 代碼如下:

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) -->設置默認值
print(tb1.x, tb1.z) --> 10 100 這里打印的就是默認值

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

復制代碼 代碼如下:

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

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

復制代碼 代碼如下:

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

記錄table的訪問

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

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

復制代碼 代碼如下:

local t = {} --原來的table
 
-- 保持對原table的一個引用
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

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

復制代碼 代碼如下:

-- 創(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

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

復制代碼 代碼如下:

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對應的是原來的table,而更新原來的table時,就會顯示錯誤提示:Attempt to update a read-only table。

總結(jié)

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

相關文章

  • Lua面向?qū)ο笾惡屠^承

    Lua面向?qū)ο笾惡屠^承

    這篇文章主要介紹了Lua面向?qū)ο笾惡屠^承,本文講解了Lua面向?qū)ο笞罨镜闹R類和繼承,需要的朋友可以參考下
    2014-09-09
  • Lua中的table淺析

    Lua中的table淺析

    這篇文章主要介紹了Lua中的table淺析,本文講解了table的構造方法、內(nèi)置函數(shù)unpack等內(nèi)容,需要的朋友可以參考下
    2014-09-09
  • linux系統(tǒng)安裝Nginx Lua環(huán)境

    linux系統(tǒng)安裝Nginx Lua環(huán)境

    因項目需求,需要在Linux系統(tǒng)下搭建一套nginx+lua的開發(fā)環(huán)境,經(jīng)過一番摸索,現(xiàn)總結(jié)如下,希望大家能夠喜歡。
    2016-12-12
  • lua日志文件處理代碼

    lua日志文件處理代碼

    本文給大家分享的是使用lua編寫的日志文件的處理代碼,非常的簡單實用,有需要的小伙伴可以參考下。
    2015-09-09
  • Mac平臺中編譯安裝Lua運行環(huán)境及Hello Lua實例

    Mac平臺中編譯安裝Lua運行環(huán)境及Hello Lua實例

    這篇文章主要介紹了Mac平臺中編譯安裝Lua運行環(huán)境及Hello Lua實例,本文給出了兩種Hello Lua示例,一種是控制臺直接輸出,通過文件編譯輸出,需要的朋友可以參考下
    2014-10-10
  • Lua腳本實現(xiàn)遞歸刪除一個文件夾

    Lua腳本實現(xiàn)遞歸刪除一個文件夾

    這篇文章主要介紹了Lua腳本實現(xiàn)遞歸刪除一個文件夾,本文給出了C++和Lua兩個版本的實現(xiàn)代碼,需要的朋友可以參考下
    2015-05-05
  • 詳解Lua中if ... else語句的使用方法

    詳解Lua中if ... else語句的使用方法

    這篇文章主要介紹了詳解Lua中if ... else語句的使用方法,是Lua入門學習中的基礎知識,需要的朋友可以參考下
    2015-05-05
  • Lua中使用table.concat連接大量字符串實例

    Lua中使用table.concat連接大量字符串實例

    這篇文章主要介紹了Lua中使用table.concat連接大量字符串實例,本文是Lua處理大量字符串的一個測試文章,測試了2種方法處理大量字符串的消耗時間,需要的朋友可以參考下
    2014-09-09
  • 安裝Nginx+Lua開發(fā)環(huán)境

    安裝Nginx+Lua開發(fā)環(huán)境

    本文主要詳細介紹了安裝Nginx+Lua開發(fā)環(huán)境的過程以及nginx+lua的配置,十分的詳盡,這里推薦給小伙伴們。
    2015-02-02
  • Lua判斷Table是否為空的方法(空的table即{})

    Lua判斷Table是否為空的方法(空的table即{})

    這篇文章主要介紹了Lua判斷Table是否為空的方法(空的table即{}),如何判斷l(xiāng)ua中的table是否是空的table呢,本文就試驗了多個方法,最后得出比較好的判斷方法,需要的朋友可以參考下
    2015-04-04

最新評論

高碑店市| 玉溪市| 岳阳县| 米脂县| 乌兰浩特市| 连江县| 麻阳| 泰来县| 宾川县| 定襄县| 武汉市| 尉氏县| 崇义县| 锡林浩特市| 门源| 长宁区| 遵义县| 拜城县| 江北区| 台中市| 宁强县| 桦川县| 博白县| 崇义县| 永昌县| 甘洛县| 南部县| 陆河县| 五家渠市| 安多县| 济源市| 浑源县| 庆阳市| 汉源县| 成武县| 丹巴县| 吉木萨尔县| 临沭县| 玛纳斯县| 绍兴市| 通城县|