Lua中的元表和元方法

Lua中的每個值都可具有元素,元表是普通的Lua表,定義了原始值在某些特定操作下的行爲,你可通過在值的元表中設置特定的字段來改變作用於改值的操作的某些特性行爲特徵,例如,當數字值作爲加法的操作數時,Lua檢查起元素中的”__add”字段是否有個函數,如果有,Lua調用它執行加法.
我們成元表中的鍵爲事件(event),稱值爲元方法(metamethod),前述例子中的事件是”add”,元方法是執行加法的函數.
可通過函數getmetatable查詢任何值的元素,
可通過函數setmetatable替換表的元素,不能從Lua中改變其他類型的元素(除了使用調試庫);必須使用C API才能做到
表和完整的用戶數據具有獨立的元素(景觀多個表和用戶數據可共享元素);每種其他類型的所有值共享一個元素,所以,所有數字共享一個元素,字符串也是,等等
元素可以控制對象的數學運算,順序比較,連接,取長,和索引操作的行爲,元素也能定義用戶數據被垃圾收集時調用的函數,Lua給這些操作的每一個都關聯了成爲事件的特定鍵,當Lua對某值執行其中一個操作時,檢查該值是否含有元表以及相應的事件,如果有,與該鍵關聯的值(元方法)控制Lua如何完成操作
元素控制後面列舉的操作,每個操作由相應的名字標識,每個操作鍵是由其名字前綴兩個下劃線”__”的字符串;例如,操作”加(add)”的鍵是字符串”__add”,這些操作的語義通過一個Lua函數描述解釋器如何執行操作做了更好的說明.
下面顯示的Lua代碼只是說明性的;真實的行爲被硬編碼到解釋器中,並且比這裏的模擬更加高效,這些描述中的所有函數(rawget,tonumber等等),在5.1中描述,特別一提,要獲取給定對象的元方法,我們使用表達式
metatable(obj)[event]
它應該唄解讀爲
rawget(getmetatable(obj) or {},event)
就是說,訪問一個元方法不會調用其它元方法,而且訪問沒有元素的對象不會失敗(只是結果爲nil)
“add”: + 操作
下面的getbinhander函數定義Lua如何選擇二元操作的處理程序,首先嚐試第一操作數,如果它的類型沒有定義該操作的處理程序,則嘗試第二操作數

function getbinhandler (op1,op2,event)
    return metatble(op1)[event] or metatable(op2)[event]
end

通過應用該函數,op1 + op2 的行爲是

function add_event(op1,op2)
    local o1,o2 = tonumber(op1), tonumber(op2)
    if o1 and o2 then
        return o1 + o2         --'+'此處是'add'的原語
    else
        local h = getbinhandler(op1, op2, "_add")
        if h then  -- 用兩個操作數調用處理程序
            return {h(op1, op2)}
        else  -- 沒有可用的處理程序:缺省行爲
            error(...)
        end
    end
end     

“sub”:- 操作,行爲類似於”add”操作.
“mul”:*
“div”:/
“mod”:%
“pow”:^(取冪)操作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章