English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Luaのテーブルでは、対応するキーを通じてアクセスして値を取得できますが、二つのテーブルに対して操作を行うことはできません。
したがって、Lua はメタテーブル(Metatable)を提供し、テーブルの動作を変更することができます。各動作には対応するメタメソッドが関連付けられます。
例えば、元テーブルを使用して、Lua がテーブルの足し算操作 a をどのように計算するかを定義できます。+b。
Lua が二つのテーブルを足し算に試みるとき、まずその二つのテーブルのうちの一つにメタテーブルがあるかをチェックし、その後 ' __add ' というフィールドがあるかをチェックします。' __add ' などの即時フィールドは、対応する値(通常は関数またはテーブル)が ' メタメソッド ' です。
メタテーブルを処理するために非常に重要な二つの関数があります:
setmetatable(table, metatable): 指定されたテーブルにメタテーブル(metatable)を設定する際、メタテーブル(metatable)に __metatable キー値がある場合、setmetatable は失敗します。
getmetatable(table): オブジェクトのメタテーブル(metatable)を返します。
以下の例では、指定されたテーブルにメタテーブルを設定する方法を示します:
mytable = {} -- 通常のテーブル mymetatable = {} -- メタテーブル setmetatable(mytable, mymetatable) -- mymetatable を mytable のメタテーブルに設定します
上記のコードは一行で直接書けることもあります:
mytable = setmetatable({}, {})
以下は返されるオブジェクトのメタテーブルです:
getmetatable(mytable) -- これは mymetatable を返します。
これは metatable で最もよく使われるキーです。
テーブルにキーを通じてアクセスする際、そのキーに値がなく、Lua はテーブルの metatable(存在する場合を仮定)の __index キーを探します。__index がテーブルを含んでいる場合、Lua はそのテーブル内で対応するキーを検索します。
我们可以在使用 lua 命令进入交互模式查看:
$ lua Lua 5.3.0 Copyright (C) 1994-2015 Lua.org, PUC-Rio > other = { foo = 3 } > t = setmetatable({}, { __index = other }) > t.foo 3 > t.bar nil
もし __index が関数を含んでいる場合、Lua はその関数を呼び出し、テーブルとキーを引数として渡します。
__index 元方法はテーブル内の要素が存在するかどうかを確認し、存在しない場合は nil を返します。存在する場合は __index が結果を返します。
mytable = setmetatable({key1 = "value1"}, { __index = function(mytable, key) if key == 「key2「 then return 「metatablevalue」 else return nil end end ) print(mytable.key1,mytable.key2)
サンプルの出力結果は以下の通りです:
value1 metatablevalue
サンプル解析:
mytable 表に {key1 = 「value1「}。
mytable はメタテーブルを設定し、メタメソッドは __index です。
mytable 表に key1、見つかった場合はその要素を返します。見つからない場合は続行します。
mytable 表に key2、見つかった場合は metatablevalue を返します。見つからない場合は続行します。
メタテーブルに __index メソッドがあるかどうかを確認します。__index メソッドが関数であれば、その関数を呼び出します。
メタテーブル内で「key」2「キーのパラメータ(mytable.key2設定済み(已設定),「key」2「パラメータが「metatablevalue」の場合、返します。それ以外の場合は mytable に対応するキーの値を返します。
以下のコードを簡単に書き換えることができます:
mytable = setmetatable({key1 = "value1「}, { __index = { key2 = 「metatablevalue」 } })」 print(mytable.key1,mytable.key2)
まとめ
Lua がテーブルの要素を検索するルールは以下の通りです: 3 のステップ:
1.テーブル内を検索し、見つかった場合はその要素を返します。見つからない場合は続行します。
2.テーブルにメタテーブルがあるかどうかを確認します。メタテーブルがない場合は nil を返します。メタテーブルがある場合は続行します。
3.メタテーブルに __index メソッドがあるかどうかを確認します。__index メソッドが nil であれば nil を返します。__index メソッドがテーブルであれば、繰り返し 1、2、3;__index メソッドが関数の場合、その関数の返値を返します。
この部分の内容は作者の環子から提供されています:https://blog.csdn.net/xocoder/article/details/9028347
__newindex 元方法はテーブルの更新に使用され、__index はテーブルのアクセスに使用されます。
あなたがテーブルの欠けているインデックスに値を代入した場合、インタプリタは __newindex 元方法を検索します:存在する場合はこの関数を呼び出し、代入操作を行いません。
以下示例演示了 __newindex 元方法的应用:
mymetatable = {} mytable = setmetatable({key1 = "value1「}, { __newindex = mymetatable })」 print(mytable.key1) mytable.newkey = "新值"}2" print(mytable.newkey,mymetatable.newkey) mytable.key1 = "新值1" print(mytable.key1,mymetatable.key1)
上記の例の実行結果は以下の通りです:
value1 nil 新值2 新值1 nil
以上の例では、テーブルに __newindex メソッドを設定しており、新しい索引キー(newkey)に値を割り当てるとき(mytable.newkey = "新値2"),会调用元方法,而不进行赋值。而如果对已存在的索引键(key1),则会进行赋值,而不调用元方法 __newindex。
以下の例では rawset 関数を使用してテーブルを更新しています:
mytable = setmetatable({key1 = "value1"}, { __newindex = function(mytable, key, value) rawset(mytable, key, "\""..value.."\"") end ) mytable.key1 = "new value" mytable.key2 = 4 print(mytable.key1,mytable.key2)
上記の例の実行結果は以下の通りです:
new value "4"
以下の例では、二つのテーブルの加算操作を示しています:
-- テーブルの最大値を計算します、table.maxnはLuaで5.2このバージョンでは使用できません -- テーブルの最大値を計算するためにカスタマイズされた関数table_maxnを使用します。これはテーブルの要素数を計算します。 function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- 二つのテーブルの加算操作 mytable = setmetatable({ 1, 2, 3 }, { __add = function(mytable, newtable) for i = 1, table_maxn(newtable) do table.insert(mytable, table_maxn(mytable)+1,newtable[i]) end return mytable end ) secondtable = {4,5,6} mytable = mytable + secondtable for k,v in ipairs(mytable) do print(k,v) end
上記の例の実行結果は以下の通りです:
1 1 2 2 3 3 4 4 5 5 6 6
__add キーはメタテーブルに含まれており、加算操作が行われます。 テーブルに対する操作リストは以下の通りです:(注意:__は二つのアンダースコアで始まるテーブルです)
パターン | 説明 |
---|---|
__add | 対応する演算子 '"'。+'. |
__sub | 対応する演算子 '"'。-'. |
__mul | 対応する演算子 '"'。*'. |
__div | 対応する演算子 '"'。/'. |
__mod | 対応する演算子 '%'。 |
__unm | 対応する演算子 '"'。-'. |
__concat | 対応する演算子 '..'。 |
__eq | 対応する演算子 '=='。 |
__lt | 対応する演算子 '<'。 |
__le | 対応する演算子 '<='。 |
__call メソッドは Lua で値を呼び出す際に呼び出されます。以下の例では、テーブルの要素の和を計算する方法を示しています:
-- テーブルの最大値を計算します、table.maxnはLuaで5.2このバージョンでは使用できません -- テーブルの最大値を計算するためにカスタマイズされた関数table_maxnを使用します。これはテーブルの要素数を計算します。 function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- メタメソッド__callを定義 mytable = setmetatable({10}, { __call = function(mytable, newtable) sum = 0 for i = 1, table_maxn(mytable) do sum = sum + mytable[i] end for i = 1, table_maxn(newtable) do sum = sum + newtable[i] end return sum end ) newtable = {10,20,30} print(mytable(newtable))
上記の例の実行結果は以下の通りです:
70
__tostring メタメソッドはテーブルの出力行動を変更するために使用されます。以下の例では、テーブルの出力内容をカスタマイズしています:
mytable = setmetatable({ 10, 20, 30 }, { __tostring = function(mytable) sum = 0 for k, v in pairs(mytable) do sum = sum + v end return "テーブルの全要素の合計は " .. sum end ) print(mytable)
上記の例の実行結果は以下の通りです:
テーブルの全要素の合計は 60
この記事から、メタテーブルはコードの機能を大幅に簡素化できることが分かりますので、Luaのメタテーブルを理解することでより簡潔で優れたLuaコードを書くことができます。