luaのクラスその4
多重継承。
「Programming Lua」の16章を参考。
-------------------------------------------------------------------------------- -- class utility -------------------------------------------------------------------------------- -- root class local g_root_class={ classname="#root#", class=function(self) return getmetatable(self).__index end, } local function g_factory(class, ...) local instance={} setmetatable(instance, class) if instance.initialize then instance:initialize(...) end return instance end -- define new class function define_class(name, ...) local base_table={...} if #base_table==0 then base_table={g_root_class} end -- new class local class_table={ classname=name, super=#base_table==1 and base_table[1] or base_table, __tostring=function(self) return string.format("<instance of: %s>", name) end, } class_table.__index=class_table -- extend setmetatable(class_table, { __index=#base_table==1 and base_table[1] or function(t, k) for i=1, #base_table do local v=base_table[i][k] if v then -- cache t[k]=v return v end end end, __call=g_factory, __tostring=function(self) return string.format("<class: %s>", name) end, }) --set global --global(name) _G[name]=class_table end -- 使う define_class("ClassA") define_class("ClassB") -- ClassAとClassBを多重継承 -- indexが被ったら先に継承した方(ClassA)が使われる define_class("ClassAB", ClassA, ClassB) local ab=ClassAB()
luaunit導入のためあるクラスの機能を分離したかったのだが、
元の変更を最小限にするために多重継承を入れてしまった。
今まで多重継承はできるだけ避けていたのだがどうなんだろう。
utf8バイト列を1文字ずつ処理する
function each_utf8(text) local i=1 return function() if i>#text then -- 終了 return end local b=string.byte(text, i) if b==0 then -- eof return elseif b<128 then -- ascii local m=string.sub(text, i, i) i=i+1 return m elseif b<192 then assert(false, 'invalid byte') return elseif b<224 then -- 2bytes local m=string.sub(text, i, i+1) i=i+2 return m elseif b<240 then -- 3bytes(japanese multibyte) local m=string.sub(text, i, i+2) i=i+3 return m elseif b<248 then -- 4bytes local m=string.sub(text, i, i+3) i=i+4 return m elseif b<252 then -- 5bytes local m=string.sub(text, i, i+4) i=i+5 return m elseif b<254 then -- 6bytes local m=string.sub(text, i, i+5) i=i+6 return m else assert(false, 'unknown') return end end end -- 使う for v in each_utf8('Abあソ漢ア') do print(v) end
UTF8文字列を1文字ずつ処理するイテレータ関数。
無さそうだったので作ってみた。
string.gmatchでもっと短く書けそうな気がしたのだができなかったのでとりあえず動くもの。