目次
概要
Luaには他言語のようなクラスという仕組みはありませんが、テーブルとメタテーブル(__index)を使うことで、クラスのような構造を実装できます。
ポイント
- Luaにはクラスはありません
- テーブル+メタテーブルでクラス風に実装する
- __indexでメソッド探索を行う
- インスタンスはsetmetatableで作る
メタテーブルとは
テーブルの動作をカスタマイズするための設定テーブルです。
通常のテーブル
local t = {}
print(t.x) -- nil(存在しないキーはnil)
そのまま値を返します。通常のテーブルは決まった動作しかしません。
メタテーブルを使う
local t = {}
local mt = { __index = function() return 0 end }
setmetatable(t, mt)
print(t.x) -- 0(存在しないキーでも0を返す)
setmetatable(t, mt)のmtがメタテーブルです。
メタテーブルを設定すると、その動作を変えられます。
以下のイメージです。
このテーブルで○○が起きたときは、この設定に従って動かしてください
クラス風の基本実装
local Color = {} -- テーブル
Color.__index = Color -- __indexを設定
function Color:new(name)
local obj = setmetatable({ name = name }, Color) -- Colorがメタテーブル
return obj
end
function Color:getName()
return self.name
end
-- 使用例
local c1 = Color:new("red")
print(c1:getName()) -- red
local c2 = Color:new("blue")
print(c2:getName()) -- blue
解説
① クラステーブル
local Color = {}
Color.__index = Color
Colorはクラスのような役割です。
__indexに自分自身を設定することで、メソッド探索先になります。
②インスタンス生成
local obj = setmetatable({ name = name }, Color)
name=nameはテーブルのキーのnameに、引数nameの値を入れているという意味です。
以下のテーブルが作成されます。
obj = {
name = "red"
}
Colorは、メタテーブルです。
メタテーブルのColorの__index=Colorにより、Color.getNameが見つかりobjからColorのメソッドを使えるようになります。
| obj ├── name = "red" ← 自分自身のデータ └── (メタテーブル = Color) └── getName ← ここから借りてくる |
③ メソッド定義
function Color:getName()
return self.name
end
:記法によりselfが自動で渡されます。
インスタンスのデータにアクセス可能です。
__index の動作
c:getName()
このとき内部では、
1.c.getNameを探す→存在しない
2.メタテーブルColor.__indexを見る
3.Color.getNameを見つけて呼び出す
これによりインスタンスからメソッドが呼べます。
なぜ __indexを外で定義するのか
Color.__index = Color
これを new() の中ではなく、外に書く理由:
- 毎回設定する必要がない
- クラス定義として明確になる
- 可読性が高い
関連の記事
