luaメタテーブルの詳細

12419 ワード

https://www.cnblogs.com/blueberryzzz/p/8947446.html
メタテーブルの役割
メタテーブルはtableまたはuserdataの操作方法を定義するためのテーブルです.
例を挙げる
local t1 = {1}
local t2 = {2}
local t3 = t1 + t2

私たちは直接2つのtableに対して+演算を実行して、間違いを報告します
lua: /usercode/file.lua:3: attempt to perform arithmetic on local 't1' (a table value)

プログラムは2つのテーブルに対して+実行をどのように実行するか分からないため、この場合、t 1の+演算をどのように実行するかをメタテーブルで定義する必要があり、c言語の演算子の再ロードに似ている.
local mt = {}
--  mt.__add   (               )                 
mt.__add = function(t1,t2) local temp = {} for _,v in pairs(t1) do table.insert(temp,v) end for _,v in pairs(t2) do table.insert(temp,v) end return temp end local t1 = {1,2,3} local t2 = {2} --  t1    mt setmetatable(t1,mt) local t3 = t1 + t2 --  t3 local st = "{" for _,v in pairs(t3) do st = st..v..", " end st = st.."}" print(st)

結果:
{1, 2, 3, 2, }

プログラムはt 1+t 2を実行すると、t 1のメタテーブルmtの__を呼び出すからであるaddメタメソッドで計算します.具体的な過程は:1.t 1にメタテーブルがあるかどうかを確認し、ある場合はt 1のメタテーブルに__があるかどうかを確認するaddメタメソッド、あれば呼び出します.2.t 2にメタテーブルがあるかどうかを確認し、ある場合はt 2のメタテーブルに__があるかどうかを確認するaddメタメソッド、あれば呼び出します.[原句]なければ間違いを報告する.したがって、t 1メタテーブルの__を定義することによってaddメタメソッドは,2つのテーブルを+番号で加算する効果を達成した.
メタテーブルのメタメソッド
関数#カンスウ#
説明
__add
演算子+
__sub
演算子-
__mul
演算子*
__ div
演算子/
__mod
演算子%
__unm
演算子-(逆)
__concat
演算子..
__eq
演算子==
__lt
演算子<
__le
演算子<=
__call
関数呼び出し時
__tostring
文字列に変換
__index
インデックスを呼び出す
__newindex
インデックスに値を割り当てる
それらの演算子は似ているので、単独では説明しません.call, __tostring, __index, __newindexの4つのメタメソッド.
__call
__callはtableを関数として使用することができます.
local mt = {}
--__call         
mt.__call = function(mytable,...) --       for _,v in ipairs{...} do print(v) end end t = {} setmetatable(t,mt) -- t         t(1,2,3)

結果:
1
2
3

__tostring
__tostringはtableを文字列に変換する動作を変更できます
local mt = {}
--      
mt.__tostring = function(t) local s = "{" for i,v in ipairs(t) do if i > 1 then s = s..", " end s = s..v end s = s .."}" return s end t = {1,2,3} --    t print(t) -- t     mt setmetatable(t,mt) --  t print(t)

結果:
table: 0x14e2050
{1, 2, 3}

__index
tableの存在しないインデックスを呼び出すと、メタテーブルの__が使用されます.indexメタメソッドは、前のメタメソッドとは異なり、_indexは関数でもtableでもよい.関数として:テーブルとインデックスをパラメータとして入力_indexメタメソッド、return戻り値
local mt = {}
--         ,           
mt.__index = function(t,key) return "it is "..key end t = {1,2,3} --      key  ,   nil print(t.key) setmetatable(t,mt) --           key  ,     __index  ,  "it is key"   print(t.key)

結果:
nil
it is key

tableとして:検索_indexメタメソッドテーブル、インデックスがある場合はインデックスに対応する値を返し、そうでない場合はnilを返します.
local mt = {}
mt.__index = {key = "it is key"}

t = {1,2,3} --      key  ,   nil print(t.key) setmetatable(t,mt) --       ,    __index    key   ,  __index  key   "it is key" print(t.key) --       ,    __index        ,   nil print(t.key2)

結果:
nil
it is key
nil

__newindex
tableに存在しないインデックスに値を割り当てると、メタテーブルの__が呼び出されます.newindexメタメソッドを関数として_newindexは関数の場合、付与文のテーブル、インデックス、付与された値をパラメータとして呼び出します.表を変えない
local mt = {}
--         ,        ,         
mt.__newindex = function(t,index,value) print("index is "..index) print("value is "..value) end t = {key = "it is key"} setmetatable(t,mt) --        key   print(t.key) --       newKey    ,      __newIndex   ,        t.newKey = 10 --   newKey      ,           ,       __newIndex   ,    t         print(t.newKey)

結果:
it is key
index is newKey
value is 10
nil

table_としてnewindexがtableの場合、tに存在しないインデックスに値を割り当てると、インデックスと値が__に割り当てられます.newindexが指すテーブルでは、元のテーブルは変更されません.
local mt = {}
-- __newindex          newTable
local newTable = {}
mt.__newindex = newTable
t = {}
setmetatable(t,mt) print(t.newKey,newTable.newKey) -- t            ,  t     __newindex         ,      t           ,   __newindex    newTable newKey      "it is newKey" t.newKey = "it is newKey" print(t.newKey,newTable.newKey)

結果:
nil nil
nil it is newKey

rawgetとrawset
テーブルの値を直接変更したり取得したりするには、rawgetメソッドとrawsetメソッドが必要になる場合があります.rawgetでは、メタテーブルの__ではなく、テーブル内のインデックスの実際の値を直接取得できます.indexメタメソッド.
local mt = {}
mt.__index = {key = "it is key"}
t = {}
setmetatable(t,mt)
print(t.key) --  rawget    t  key   print(rawget(t,"key"))

結果:
it is key
nil

rawsetでは、メタテーブルの__ではなく、テーブル内のインデックスに直接値を割り当てることができます.newindexメタメソッド.
local mt = {}
local newTable = {}
mt.__newindex = newTable
t = {}
setmetatable(t,mt)
print(t.newKey,newTable.newKey) --  rawset   t newKey     rawset(t,"newKey","it is newKey") print(t.newKey,newTable.newKey)

結果:
nil nil
it is newKey    nil

メタテーブルの使用シーン
tableとしてのメタテーブル
tableにメタテーブルを設定することでluaでオブジェクト向けプログラミングを実現できます.
userdataのメタテーブルとして
userdataとメタテーブルによりluaにおけるc中の構造へのオブジェクト向けアクセスを実現できる.
 
ラベル:lua