Lua のオブジェクト指向
できるだけ同じ名前を出さないという方向で書きかたを考えてみる。
#!/usr/bin/lua
List = {
new = function ()
return setmetatable({
-- instance variables
firstIndex = 0,
lastIndex = -1,
}, { __index = List.prototype })
end,
prototype = {
unshift = function (self, value)
self.firstIndex = self.firstIndex - 1
self[self.firstIndex] = value
return self
end,
push = function (self, value)
self.lastIndex = self.lastIndex + 1
self[self.lastIndex] = value
return self
end,
shift = function (self)
local first = self.firstIndex
if first > self.lastIndex then
return nil
end
local value = self[first]
self[first] = nil
self.firstIndex = first + 1
return value
end,
pop = function (self)
local last = self.lastIndex
if self.firstIndex > last then
return nil
end
local value = self[last]
self[last] = nil
self.lastIndex = last - 1
return value
end,
clear = function (self)
for i,v in ipairs(self) do
self[i] = nil
end
self.firstIndex = 0
self.lastIndex = -1
end,
size = function (self)
return self.lastIndex - self.firstIndex + 1
end,
first = function (self)
return self[self.firstIndex]
end,
last = function (self)
return self[self.lastIndex]
end,
},
}
l = List.new()
print(l)
-- basic tests
l:push(1)
l:push(2)
assert(l:pop() == 2)
assert(l:pop() == 1)
l:push(1)
l:unshift(2)
assert(l:size() == 2)
assert(l:first() == 2)
assert(l:last() == 1)
assert(l:shift() == 2)
assert(l:shift() == 1)
assert(l:size() == 0)
l:push(1)
assert(l:size() == 1)
l:clear()
assert(l:size() == 0)
-- multi-obj tests
l1 = List.new()
l1:push(1)
l:push(1)
l1:push(2)
l:push(2)
assert(l1:pop() == 2)
assert(l:pop() == 2)
assert(l1:pop() == 1)
assert(l:pop() == 1)
-- prototype 書きかえてみる
List.prototype.hoge = function ()
return "hoge"
end
assert(l:hoge() == "hoge")
-- プロトタイプとってきたいとき
assert(getmetatable(l).__index == List.prototype)
print "Tests are completed"new の中ででてきてしまう。うーん。
Lua は基本的にオブジェクト指向がどうこうっていう話はあんまりなくて、テーブルとメタテーブルをごにょって自分でやるらしい。
あるテーブルはメタテーブルを持てて (そしてメタテーブルもまたテーブルなので、さらにメタテーブルを持てるはず?)、そのメタテーブルに定義された __hoge なキーの値が特別な意味をもってたりする (演算子のオーバーロードもこれでやるみたい。ためしてない)。__index キーには元のテーブルでキーが見付からないときに使われるテーブルをセットする。
self を暗黙的に使うシンタックスもあるけど、名前が何回もでてきてうざくなる。