プログラミングの魔物

エラー、バグ、仕様変更と戦うブログ

Luaでオブジェクト指向プログラミング考察3

先日の考察ではLuaのクラスでプライベート変数を扱った。
しかし、以前のプログラムではオブジェクトの解放後もプライベート変数がメモリ上に残ったままになってしまう。

private.lua

local _M = {}
local _ = {}	--プライベート変数を保持するテーブル

function _M:new(o)
  o = o or {}
  _[o] = {}
  self.__index = self
  return setmetatable(o, self)
end

function _M:setA(v)
  _[self].a = v
end

function _M:showA()
  print(_[self].a)
end

--プライベート変数テーブルを表示する
function _M:showPrivateTable()
	for k1, v1 in pairs(_) do
		for k2, v2 in pairs(v1) do
			print(k2, v2)
		end
	end
end

return _M

main.lua

private = require "private"

o = private:new()

o:setA(10)

o:showA()  --> 10

--オブジェクトを破棄する
o = nil
collectgarbage();

--オブジェクトが破棄されてもプライベート変数は解放されていない
private:showPrivateTable()  --> a       10

というわけで弱いテーブルを使ってガベージコレクション時に解放されるようにする。

--private.luaのプライベートテーブル宣言後に1行追加する
local _ = {}	--プライベート変数を保持するテーブル
setmetatable(_, {__mode = "k"})  --プライベート変数テーブルを弱いテーブルにする

--以下同じ

これでガベージコレクション時にプライベート変数も破棄され、private:showPrivateTable()を呼び出しても表示されなくなる。