目次
概要
Luaではテーブルにメタテーブル(metatable)を設定することで、参照や演算などの挙動をカスタマイズできます。
その代表例が__indexで、存在しないキーにアクセスしたときの動作を定義できます。
まとめると
- setmetatableでテーブルにメタテーブルを設定できる
- __indexを使うと存在しないキーの参照動作を変更できる
- __indexは関数だけでなくテーブルも指定可能
存在しないキー参照時の動作を変更する
setmetatableを使用すると振る舞いを変える・動作を追加できます。
local color1 = {
a = "red"
}
local mt = {
__index = function(tbl, key)
return "That key does not exist."
end
}
setmetatable(color1, mt)
print(color1.a) -- red
print(color1.b) -- That key does not exist.
1行目のcolor1は通常のテーブルです。
5行目のmtはメタテーブルです。
11行目のsetmetatable(color1,mt)により、color1にメタテーブルを設定します。
14行目のcolor1.b のように存在しないキーを参照すると通常は nil が返りますが
__index が定義されているため、__index(tbl, key) が呼ばれ戻り値がそのまま参照結果になります。
setmetatable を使わない場合
local color1 = { a = "red" }
print(color1.a) -- red
print(color1.b) -- nil
存在しないキーは単純にnilを返します。これがデフォルトの挙動です。
__indexの重要ポイント
1. 関数だけでなくテーブルも指定できる
local default = { b = "blue" }
local color1 = { a = "red" }
setmetatable(color1, { __index = default })
print(color1.a) -- red
print(color1.b) -- blue
__index=テーブルの場合、存在しないキーはそのテーブルから参照されます。
2. 疑似オブジェクト指向(メソッド共有)に使う
local Dog = {}
Dog.__index = Dog
function Dog:speak()
print("barks")
end
local dog = setmetatable({}, Dog)
dog:speak() -- barks
1行目は、空のテーブルを作成しています。これをクラス(設計図)として使います。
2行目は、見つからないキーはDogを見に行くという意味です。
8行目は、インスタンス生成です。
{}→空のインスタンス
Dog→メタテーブルとして設定
これによりdogはDogを参照できるようになります。
流れ
1.9行目、dog.speakを探す→無い(dogは空テーブル)
2.メタテーブルの__indexを確認→Dogが設定されている
3.Dog.speakを探す→見つかる
4.Dog.speak(dog)として実行→barks(吠える)が出力される
3.__indexが呼ばれる条件
print(t.y) -- yというキーは定義していない → __index が呼ばれる
__indexが呼ばれる条件は、テーブルにそのキーが見つからないときです。
関連の記事
