1. 程式人生 > >Lua中rawset 函式使用

Lua中rawset 函式使用

當我們只想單純的呼叫table裡的欄位或者給table欄位賦值時,我們可以通過rawget函式來忽略元表的__index作用,只從table中
查詢例如:

    local father = {
    	--house=1,
    	sayHello = function()
            print("大家好,我是father.");
        end
    }
    
    local temp ={
        
        __index = father,
        __newindex = function(table, key)
            print(key .. "欄位是不存在的,不允許給它賦值!");
        end
    }
    
    son = {
    	car=1
    }
    setmetatable(son, temp) --把son的metatable設定為father
    print(rawget(son, "house"));
    print(rawget(son, "car"));
    rawset(son, "house", "10");
    rawset(son, "sayHello", function()
            print('============')
        end);
    print(son.house);
    son.sayHello()

上面程式碼輸出:

nil
1
10
============

rawget函式的第一個引數是要呼叫的table,第二個引數是table的欄位名。
因此,通過rawget呼叫son的house欄位,返回nil,而呼叫car欄位,則能正確取得值。
同樣的是,rawset函式可以忽略元表的__newindex功效,單純地給house賦值

另外在網上看到有個人用__index和__newIndex實現了一個只讀的函式,挺有意思的這裡貼一下

local function readOnly(t)
    local newT = {};
    local mt = {
        __index = t,
        __newindex = function()
            error("別修改我!我是隻讀的!");
        end
    }
    setmetatable(newT, mt);
    return newT;
end
local days = readOnly({"星期一", "星期二", "星期日"});
  
days[2] = "星期三哪去了啊?" ;

輸出:[LUA-print] LUA ERROR: [string "src/main.lua"]:130: [string "src/main.lua"]:76: 別修改我!我是隻讀的!

沒錯,通過readOnly產生的table,是無法進行賦值操作的。
 
那麼,原理呢?我們來一步步思考吧:

 

a.首先,readOnly會建立一個新的table,然後把我們傳進去的table作為__index元方法。

b.元表裡還增加了__newindex,用來阻止不存在欄位的賦值操作。

c.readOnly返回的table已經不是我們原來的table了,它是一個空的table,但是它被設定了一個新的元表。

d.開始對days執行賦值操作:days[2] = “星期三哪去了啊?” 。

e.days是一個空的table,所以它不存在這個欄位,也因此,會呼叫__newindex元方法,賦值失敗。

f.如果只是呼叫days,不進行賦值,如:print(days[2]); 則能正常輸出欄位值,因為days的元表裡有__index元方法。雖然days中不存在2這個欄位,但是可以通過__index找到這個欄位。
 
總而言之,最終,days成為了一個只可以讀取,不能進行賦值操作的table。

節選自:https://www.jb51.net/article/55160.htm