【Lua高級教程】什麼是Metatable舉例說明

什麼是Metatable

metatable是Lua中的重要概念,每個table均可以加上metatable,以改變相應的table的行爲。函數

Metatables舉例

lo_table =lo_meta_table =(lo_table)

上邊的代碼也能夠寫成一行,以下所示spa

-- setmetatable函數的返回值,就是該函數的第一個參數lo_table = setmetatable({}, {})

建立複雜的元表變量

metatable能夠包括任何東西,metatable特有的鍵通常以__開頭,例如__index__newindex,它們的值通常是函數或其餘table。3d

lo_table = setmetatable({}, {
  __index = function(lo_table, key)    if key == "foo" then      return 0    else      return table[key]    end  end})

__index

  這是metatable最經常使用的鍵了。code

  當你經過鍵來訪問table的時候,若是這個鍵沒有值,那麼Lua就會尋找該table的metatable(假定有metatable)中的__index鍵。若是__index包含一個表格,Lua會在表格中查找相應的鍵。ip

-- 建立元表變量lo_meta_table = { name = "藍鷗" }-- 設置該元表變量做爲關係變量的lo_table = setmetatable({}, { __index = lo_meta_table })-- 打印lo_table變量的姓名 藍鷗print(lo_table.name)-- 打印lo_table變量年齡 nilprint(lo_table.age)

  若是__index包含一個函數的話,Lua就會調用那個函數,table和鍵會做爲參數傳遞給函數。字符串

-- 建立元表變量lo_meta_table = { 
    name = "藍鷗" ,
    action = function ( param )        -- body        if(param == "學生") then            print("讓教育迴歸本質")        else            print("讓藍鷗維護教育")        end    end}-- 設置該元表變量做爲關係變量的lo_table = setmetatable({}, { __index = lo_meta_table })-- 打印lo_table變量的動做 讓教育迴歸本質print(lo_table.action("學生"))-- 打印lo_table變量的動做 讓藍鷗維護教育print(lo_table.action("肖浩"))-- 打印lo_table變量年齡 nilprint(lo_table.age)

 

__newindex

相似__index__newindex的值爲函數或table,用於按鍵賦值的狀況。get

-- 建立元表變量lo_meta_table = {}-- 設置該元表變量做爲關係變量的lo_table = setmetatable({}, { __newindex = lo_meta_table })-- 設置lo_table變量的name關鍵字的值lo_table.name = "藍鷗"-- 打印lo_meta_table元表變量name關鍵字的值值print(lo_meta_table.name)-- 打印lo_table變量name關鍵字的值print(lo_table.name)

 

-- 建立元表變量lo_meta_table = {}-- 設置該元表變量做爲關係變量的lo_table = setmetatable({}, { __newindex = function(t, key, value)    if type(value) == "number" then      rawset(t, key, value * value)    else      rawset(t, key, value)    end  end})-- 設置lo_table變量的name關鍵字的值lo_table.name = "藍鷗"-- 設置lo_table變量的age關鍵字的值lo_table.age = 3-- 打印lo_meta_table元表變量name關鍵字的值值print(lo_meta_table.name)-- 打印lo_table變量name關鍵字的值print(lo_table.name)-- 打印lo_meta_table元表變量age關鍵字的值值print(lo_meta_table.age)-- 打印lo_table變量age關鍵字的值print(lo_table.age)

上面的代碼中使用了rawgetrawset以免死循環。使用這兩個函數,能夠避免Lua使用__index__newindexstring

運算符

利用metatable能夠定義運算符,例如+io

-- 建立重載+號行爲的表變量lo_table = setmetatable({ 1, 2, 3 }, {
  __add = function(lo_table, other)
    new = {}    -- 遍歷元素加other    for _, v in ipairs(lo_table) 
        do table.insert(new, v + other) 
    end    return new  end})-- 進行計算+lo_table = lo_table + 2-- 打印獲得的結果print(lo_table[1])print(lo_table[2])print(lo_table[3])

__index__newindex不一樣,__mul的值只能是函數。與__mul相似的鍵有:table

  • __add (+)

  • __sub (-)

  • __div (/)

  • __mod (%)

  • __unm 取負

  • __concat (..)

  • __eq (==)

  • __lt (<)

  • __le (<=)

 

__call

__call使得你能夠像調用函數同樣調用table

t = =  (a + b + c) *, , , )

 

__tostring

最後講下__tostring,它能夠定義如何將一個table轉換成字符串,常常和 print 配合使用,由於默認狀況下,你打印table的時候會顯示 table: 0x7f86f3d04d80 這樣的代碼

lo_table = setmetatable({ 1, 2, 3 }, {
  __tostring = function(lo_table)
    sum = 0    for _, v in pairs(lo_table) 
    do 
        sum = sum + v 
    end    
    return "計算的結果是: " .. sum  end})-- prints out "計算的結果是: 6" print(lo_table)

 

建立一個簡單的向量Vector類

Vector = {}
Vector.__index = Vectorfunction Vector.new(x, y)  return setmetatable({ x = x or 0, y = y or 0 }, Vector)end-- __call關鍵字setmetatable(Vector, { __call = function(_, ...) return Vector.new(...) end })-- + 運算符function Vector:__add(other)  -- ...     local result = Vector(self.x + other.x,self.y + other.y)     return resultend-- __tostring關鍵字function Vector:__tostring()    -- body    return "x: " .. self.x .. " y: " .. self.yenda = Vector.new(12, 10)
b = Vector(20, 11)
c = a + bprint(a)print(c)
相關文章
相關標籤/搜索