TI-Nspire & Lua / スクリプティングのヒント / メタテーブルを使う 6 / __index を利用してクラスふうにしてみる

参考: お気楽 Lua プログラミング超入門, リスト 4 およびリスト 5

-- メタメソッドを格納するためのテーブルを用意する。このテーブルがいわゆるクラスに相当する。
Class = {}

-- 例として、テーブルの任意の位置に値をセットするためのメタメソッドを定義して Class テーブルに登録する。
function Class.setValue(self, where, what)
   rawset(self, where, what) -- self[where] = what と同じこと。
end

-- Class クラスのインスタンス (すなわちメタテーブルのセットされたテーブル) を作るためのコンストラクタ new を定義し、これも Class テーブルに登録する。
-- ここでは、要素数が 2 つのテーブルにメタテーブルを設定して返す。
function Class.new(a, b)
   return setmetatable({a, b}, {__index = Class})
end


------------------
-- 確認してみる --
------------------

-- メタテーブルの適用されたテーブル (すなわち Class クラスのインスタンス) を 2 つ新たに作る。
instTable_1 = Class.new(10, 20)
instTable_2 = Class.new("aaa", "bbb")


-- 出来たインスタンスの中身を確認してみる。存在しているフィールドだけ (すなわち [1] と [2] だけ) を参照する。
print("test_1: ", instTable_1[1], instTable_1[2], instTable_2[1], instTable_2[2])


-- 今度は instTable_1 テーブルに存在しないフィールド (["setValue"]) を参照してみる。
-- 参照しても見つからないので、__index イベントに従って Class テーブルの中身が探索される。
-- すると ["setValue"] フィールド (中身はメソッド) が見つかったので、そのメソッドが引数 (instTable_1, 1,  99) で実行される。
-- これで、instTable_1 テーブルの 1 番目 (すなわち instTable_1[1]) が数値 99 にセットされた。
instTable_1.setValue(instTable_1, 1, 99)
print("test_2: ", instTable_1[1], instTable_1[2], instTable_2[1], instTable_2[2])

-- “インスタンス.メソッド(第 1 引数)” は “インスタンス:メソッド()” とも書ける。
-- このコロン記法の場合は、インスタンスの値 (ここではテーブル) が第 1 引数 (例として定義したメソッドの self 引数) としてメソッドに渡される。
-- 今度はこの書きかたで instTable_2 テーブルの 2 番目 (すなわち instTable_2[2]) を書き換えてみる。
instTable_2:setValue(2, "ccc")
print("test_3: ", instTable_1[1], instTable_1[2], instTable_2[1], instTable_2[2])

f:id:ti-nspire:20170214091017p:plain
 

-- メソッド自体もコロン記法で書ける。
Class = {}
function Class:setValue(where, what)
   rawset(self, where, what)
end
function Class:new(a, b)
   return setmetatable({a, b}, {__index = Class})
end

-- 確認してみる。
instTable_1 = Class:new(100, 200)
instTable_2 = Class:new("AAA", "BBB")
print("test_1: ", instTable_1[1], instTable_1[2], instTable_2[1], instTable_2[2])

instTable_1:setValue(1, 999)
print("test_2: ", instTable_1[1], instTable_1[2], instTable_2[1], instTable_2[2])

instTable_2:setValue(2, "CCC")
print("test_3: ", instTable_1[1], instTable_1[2], instTable_2[1], instTable_2[2])

f:id:ti-nspire:20170214091053p:plain