![](https://habrastorage.org/webt/pw/h-/ka/pwh-kakokqutguzo8rusfsaqezm.png)
ãã®èšäºãæžãããã«ãç§ã¯Luaã®ã¡ã¿ããŒãã«ãšOOPã«é¢ããå€æ°ã®è³ªåã«ä¿ãããŸãããããã¯ãã®èšèªã®åŠç¿è ã«ãšã£ãŠæãå°é£ã§åé¡ã®ããã»ã¯ã·ã§ã³ã§ããããã§ããããããLuaã¯åå¿è ããã³ã¡ã¿ããŒãã«ã®å©ããåããŠãè€éãªã¿ã¹ã¯ã«å¯Ÿããé©ç°çã§éåžžã«ãšã¬ã¬ã³ããªãœãªã¥ãŒã·ã§ã³ã䜿çšã§ããããšãèãããšãéçºçšã®è³æããåŸã§ãæ®ãããšã¯äŸ¡å€ããããŸããã
ãã®åºçç©ã§ã¯ãLua 5.1-5.3ã®ããŒãžã§ã³çšã®ãã¹ãŠã®æšæºã¡ã¿ã¡ãœãããäŸãšãšãã«èª¬æããŸãã å§ããŸãããã
ã¡ã¿ããŒãã«
ããã¯äœã§ãã
å®éãã¡ã¿ããŒãã«ã¯éåžžã®ããŒãã«ãšéãã¯ãããŸããããã³ã³ãããŒã«ããŒãã«ãšããŠãªã¹ããããŠããç¹ãç°ãªããŸãã
æŠç¥çã«ã¯ãããšãã°æ¬¡ã®ããã«æ³åã§ããŸãã
![](https://habrastorage.org/webt/nd/eo/14/ndeo14kgyseidba6hp6xorhpkkw.png)
ã¡ã¿ããŒãã«ã¯ãã¢ã¯ã·ã§ã³ã«å¯Ÿããã¡ã€ã³ããŒãã«ã®åå¿ã説æããŸããããšãã°ãããŒãã«ãé¢æ°ãšããŠåŒã³åºããããä»»æã®å€ã§ããŒãã«ãåå²ããããç¹å¥ãªããŒã®ãããã§ãããŒãã«ããããŒãæœåºããããšããŸãïŒç¹ã«æèšããªãéããLua 5.1ïŒïŒ
äžè¬çãªã¡ã¿ã¡ãœãã
- __index-å ã®ããŒãã«ãååšããªãå Žåã«ããŒãæ¢ãé¢æ°ãŸãã¯ããŒãã«ã
- __newindex-ããŒãã«ã«* new *ããŒãè¿œå ããæ¹æ³ã®æ©èœã¯ãæ¢åã®ãã®ã«åœ±é¿ããŸããã
- __call-ããŒãã«ãé¢æ°ãšããŠåŒã³åºããããšãã«åŒã³åºãããé¢æ°ã
- __tostring-ããšãã°ãprintãŸãã¯tostringã䜿çšããŠã__ concatãšçµã¿åãããŠãããŒãã«ãæååã«å€æããããšãããšãã«åŒã³åºãããé¢æ°ã
- __concat-ããŒãã«ãäœããšé£çµããããšãããšãã«åŒã³åºãããé¢æ°ã¯ã__ tostringãšçµã¿åããããŸãã
- __metatable-ãã®ããŒãã«ããã¡ã¿ããŒãã«ãååŸããããšããŠè¿ãããå€ã«ãããã¡ã¿ããŒãã«ãé衚瀺ã«ã§ããŸãã
- __mode-ã¬ããŒãžã³ã¬ã¯ã·ã§ã³äžã«ããŒãã«å ã®ãªã³ã¯ã®ã匷床ããå¶åŸ¡ããæååãããã䜿çšããŠã匱ãªã³ã¯ããŒãã«ãŸãã¯ãšãã§ã¡ãã³ãäœæã§ããŸãã
- __gc-ãŠãŒã¶ãŒããŒã¿ïŒ5.1+ïŒãŸãã¯ããŒãã«ïŒ5.2+ïŒãã¬ããŒãžã³ã¬ã¯ã¿ãŒã«ãã£ãŠåéããããšãã«åŒã³åºãããé¢æ°ïŒ5.1ã§æ¬åœã«å¿ èŠãªå ŽåïŒ-䜿çšããæ¹æ³ããããŸãã
- __len-ïŒïŒ5.2+ïŒæŒç®åã䜿çšããŠããŒãã«ã®é·ããèšç®ããããšãããšãã«åŒã³åºãããé¢æ°ã
- __pairs-é¢æ°ãç¹å®ã®ããŒãã«ïŒ5.2+ïŒã®ãã¢å埩åã®ä»£æ¿ã
- __ipairs-é¢æ°ãipairsïŒ5.2+ïŒã®ä»£æ¿;
æ°åŠçã¡ã¿ã¡ãœãããšæ¯èŒïŒé¢æ°ïŒ
- __add-ïŒ+ïŒè¿œå ;
- __sub-ïŒ-ïŒæžç®;
- __mul-ïŒ*ïŒä¹ç®;
- __div-ïŒ/ïŒéšé;
- __pow-ïŒ^ïŒã¹ãä¹;
- __mod-ïŒïŒ ïŒã¢ãžã¥ãé€ç®;
- __idiv-ïŒ//ïŒæŽæ°éšãåé€ããé€ç®ïŒ5.3+ïŒ;
- __eq-ïŒ==ïŒçå€æ¯èŒ;
- __lt-ïŒ<ïŒæ¯èŒãããå°ããããå察æ¹åã§èªåçã«å®è¡ãããåŒæ°ãéã«ããŸãã
- __le-ïŒ<=ïŒæ¯èŒã以äžã;
ãããæäœïŒæ©èœã5.3以éã®ã¿ïŒ
- __band-ïŒïŒïŒããããŠã;
- __bor-ïŒ|ïŒ "OR";
- __bxor-ïŒãïŒæä»çãªãORãïŒaãbïŒ;
- __bnot-ïŒãïŒ "NO"ïŒãaïŒ;
- __bshl-ïŒ<<ïŒãããå·Šã·ããã
- __bshr-ïŒ>>ïŒããããå³ã«ã·ããããŸãã
äŸ
玢åŒ
æãäžè¬çãªã¡ã¿ã¡ãœããã®1ã€ã§ãããæãå€ãã®è³ªåãåŒãèµ·ãããŠããŸãã
åŒæ°ïŒselfãkeyïŒãæã€ããŒãã«ãŸãã¯é¢æ°ã«ãªããŸããselfã¯æ€çŽ¢ããããŒãã«ã§ãkeyã¯å€ãååŸããããŒã§ãã
ãã®ã¡ã¿ã¡ãœããã«åºã¥ããŠãOOPããããã·ããŒãã«ãããŒãã«ã®ããã©ã«ãå€ãªã©ãå€æ°ã®æ©èœãæ§ç¯ãããŸãã
ãã®ããŒãã«ã®æ£ç¢ºãªããŒãååŸããå¿ èŠãããå Žåã¯ãæ害ã«ãªãå¯èœæ§ããããŸãããã®ãããªå Žåã¯ãããŒãã«ã®ããã©ã«ãã®ã¢ã¯ã»ã¹é¢æ°ã§ããé¢æ°å€= rawgetïŒããŒãã«ãããŒïŒã䜿çšããŸãïŒããŒã§å€ãååŸããããšãããšããã€ãã³ãŒãã§åŒã³åºãããŸãïŒ ã
--[[1]] foo = {} foo.key = 'value' --[[2]] mt = {__index = foo} -- setmetatable --[[3]] bar = setmetatable({}, mt) bar.key2 = 'value2' -- : --[[4]] print('bar.key2', bar.key2) --> 'value2' --[[5]] print('bar.key', bar.key) --> 'value' --[[6]] bar.key = 'foobar' foo.foo = 'snafu' print('bar.key', bar.key) --> 'foobar' print('bar.foo', bar.foo) --> 'snafu' print('bar.foobarsnafu', bar.foobarsnafu) --> nil --[[7]] foo = {key = 'FooBar'} -- bar = setmetatable({}, {__index = foo}) snafu = setmetatable({}, {__index = bar}) print('snafu.key', snafu.key) --> 'FooBar' --[[8]] foo = {} foo.__index = foo setmetatable(foo, foo) -- print('foo.key', foo.key) --> error: loop in gettable print('foo.__index', foo.__index) --> "table: 0x12345678" print('rawget(foo, "key")', rawget(foo, "key")) --> nil --[[9]] foo = {} foo.key = 'value' setmetatable(foo, {__index = function(self, key) return key end}) print('foo.key', foo.key) --> 'value' print('foo.value', foo.value) --> 'value' print('foo.snafu', foo.snafu) --> 'snafu' --[[10]] fibs = { 1, 1 } setmetatable(fibs, { __index = function(self, v) self[v] = self[v - 1] + self[v - 2] return self[v] end })
ããã§äœãèµ·ãã£ãŠããŸããïŒ
1. foo-æã£ãŠããªãããŒãæ¢ãããŒãã«ã
2. mtã¯ãããŒ__index = fooãæã€ããŒãã«ã§ãã ã¡ã¿ããŒãã«ã®ãããªãã®ã«ã¢ã¿ãããããšããããŒããªãå Žåã¯ãfooã§ããããèŠã€ããŠãã ãããããšè¡šç€ºãããŸãã
3.ã¡ã¿ããŒãã«mtã空ã®ããŒãã«ïŒããŒã«ãªãïŒã«ãã§ãŒã³ããããã»ã¹ã次ã«ç€ºããŸãã
4.ããŒãã«ããŒãžã®çŽæ¥ã¢ã¯ã»ã¹ã®äŸã ãã®å Žåãéåžžã®ããã«ããŒããŒãã«ããããŒãååŸããŸãã
5. __indexã®ããŒãžã®ã¢ã¯ã»ã¹ã®äŸã ãã®å ŽåãããŒ["key"]ã¯barããŒãã«ã«ãããŸãããfooããŒãã«ã®__indexã¡ã¿ããŒãã«ã§æ€çŽ¢ããŸãã
6.æ確åïŒããŒããŒãã«ã«ããŒããŒãè¿œå ãããšããã®äžã«èŠã€ãããå€ãååŸããããšãããšãã¡ã¿ã¡ãœãããã§ãŒã³ã¯åŒã³åºãããŸããã ãããã["foo"]ãªã©ã®ãã®ä»ã®ååšããªãããŒã¯ãã¹ãŠãã¡ã¿ã¡ãœãããã§ãŒã³ãåŒã³åºãç¶ããŸãã ããŒ["foobarsnafu"]ã¯äž¡æ¹ã®ããŒãã«ã«ååšããããã®æå³ã¯éåžžnilã§ãã
7.ã€ã³ããã¯ã¹ã䜿çšãããšãæ€çŽ¢ãã§ãŒã³ãäœæã§ããŸãã ãã®å ŽåãããŒæ€çŽ¢ã¢ã«ãŽãªãºã ã¯æ¬¡ã®ãšããã§ãã
1. snafuããŒãã«ã§ããŒ["key"]ãæ¢ããŠããŸãã
2.èŠã€ãããŸããã snafuã¡ã¿ããŒãã«ã«ã¯ãããŒããŒãã«ãæã__indexããŒããããŸãã ç§ãã¡ã¯ãããèŠãŠããŸãã
3.åã³èŠã€ãããŸããã ããããfooããŒãã«ãæã__indexããŒãæã€ã¡ã¿ããŒãã«ããããŸãã æ¢ããŠããŸãã
4.èŠã€ããïŒ ãããããŒã§ããããã®æå³ã¯ãFooBarãã§ãïŒ
![](https://habrastorage.org/webt/js/mq/pr/jsmqprpne1ts9mqlhcjxhxy0cj4.png)
8.ãã®å Žåãããèªäœã«çãã__indexããŒãæã€ããŒãã«ãäœæããããèªäœã®ã¡ã¿ããŒãã«ãšããŠèšå®ããŸãã äžè¶³ããŠããããŒã®å€ãååŸããããšãããšãå éšã§æ€çŽ¢ãè©Šè¡ãã__ indexã¡ã¿ããŒãã«ãããã²ãŒãããŠããã«æ€çŽ¢ããååž°ãµã€ã¯ã«ãçºçããŸãã ãããã£ãŠãéããæ€çŽ¢ãã§ãŒã³ãå®è¡ããªãæ¹ãè¯ãã§ãã rawgetã䜿çšããå Žåãã¡ã¿ã¡ãœããã¯åŒã³åºãããããã®ããŒã®æ£ç¢ºãªå€ãååŸãããŸãã
9. __indexããŒãšããŠãã¡ã¿ããŒãã«ã¯2ã€ã®åŒæ°ãæã€é¢æ°ãæã€ããšãã§ããŸã-self-ããŒãã«èªäœãkey-å€ãååŸãããããŒã é¢æ°ã®æ»ãå€ãå€ã«ãªããŸãã ããã«ãããããŒãã«ã«ä»»æã®ã€ã³ããã¯ã¹ãäœæãããããããã·ãäœæãããã§ããŸãã
10. WikipediaããäŸãåãäžããŸãã ãã®å ŽåãfibsããŒãã«ã®__indexã¯ãã¡ã¢åã䜿çšããŠãã£ããããæ°ã®å€ãèªåçã«åèšç®ããŸãã printïŒfibs [10]ïŒã¯ã10çªç®ã®ãã£ããããæ°ãåºåããŸãã æ¬ èœããããŒãã«å€ã®ååž°çãªèšç®ãä»ããŠæ©èœããŸãã åŸç¶ã®å€ã¯ããŒãã«ã«ã¡ã¢ãããŸãã ç解ããã«ã¯å°ãæéãããããŸããfibs[v-1]ãååšããªãå Žåãfibs [v]ãšåãã¢ã¯ã·ã§ã³ã»ãããå®è¡ãããŸãã
Newindex
ããŸãäžè¬çãªã¡ã¿ã¡ãœããã§ã¯ãããŸããããéããããŒãã«ã®äœæããã£ã«ã¿ãªã³ã°ãŸãã¯ãããã·åŠçãªã©ã«äŸ¿å©ãªããšããããŸãã
åžžã«åŒæ°ïŒselfãkeyãvalueïŒãæã€é¢æ°ã®ã¿ã«ããããšãã§ããŸãã
æ害ãªå Žåãããããããã®ã¡ã¿ã¡ãœããã匷å¶çã«äœ¿çšããªãå ŽåãrawsetïŒselfãkeyãvalueïŒé¢æ°ã䜿çšãããŸããããã¯ãããŒãã«ã®ããã©ã«ãé¢æ°ã§ãã
--[[1]] foo = {} mt = {} function mt.__newindex(self, key, value) foo[key] = value end bar = setmetatable({a = 10}, mt) bar.key = 'value' print('bar.key', bar.key) --> nil print('foo.key', foo.key) --> 'value' --[[2]] bar.a = 20 print('bar.a', bar.a) --> 20 --[[3]] mt = {} function mt.__newindex(self, key, value) if type(value) == 'number' then -- __newindex rawset(self, key, value) end end foo = setmetatable({}, mt) foo.key = 'value' foo.key2 = 100500 print('foo.key', foo.key) --> nil print('foo.key2', foo.key2) --> 100500
1.ããã¯ã__ newindexã¡ã¿ã¡ãœããã䜿çšããŠãããã·ããŒãã«ãä»ããŠããŒãè¿œå ããæãç°¡åãªäŸã§ãã ããŒããŒãã«ã«è¿œå ãããã¹ãŠã®æ°ããå€ããŒã¯ãé¢æ°ã«åŸã£ãŠfooã«è¿œå ãããŸãã èªå·±ããã®å ŽåãããŒããŒãã«ã
2. __newindexã¯ãååšããªãããŒã«ã®ã¿é©çšãããŸãã
3.æ°å€ã®ã¿ãããŒãã«ã«è¿œå ã§ãããã£ã«ã¿ãŒé¢æ°ã®äŸã åæ§ã«ããæ°åããŒã®ã¿ãè¿œå ãããããã§ãã¯ããããè¡ããŒãã«çªå·ãªã©ã®ããã«äºåã«ããã€ãã®ããŒãã«ãäœæãã察å¿ãããã®ã«å€ãè¿œå ããããšãã§ããŸãïŒåé¡/ãã©ã³ã¹ãªã©ïŒã
é»è©±ãã
ãã®ã¡ã¿ã¡ãœããã¯ãèŠçŽ ãåæžããããããŒãã«ã䜿çšããŠé¢æ°ã®ããã©ã«ãã¡ãœãããåŒã³åºããããã¯ã©ã¹ããŒãã«ãé¢æ°ãšããŠåŒã³åºããŠãªããžã§ã¯ããååŸããéã®OOPãå°ãå¿«é©ã«ãããããã®ã«äŸ¿å©ã§ãã
--[[1]] mt = {} function mt.__call(self, a, b, c, d) return a..b..c..d end foo = setmetatable({}, mt) foo.key = 'value' print(foo(10, 20, 30, '!')) --> 102030! print(foo.key) --> 'value' print(foo.bar) --> nil --[[2]] mt = {} -- - , -- : a, b, c, d = ... function mt.__call(self, ...) return self.default(...) end foo = setmetatable({}, mt) function foo.mul2(a, b) return a * b end function foo.mul3(a, b, c) return a * b * c end foo.default = foo.mul2 print('foo.mul2(2, 3)', foo.mul2(2, 3)) --> 6 print('foo.default(2, 3)', foo.default(2, 3)) --> 6 print('foo.mul3(2, 3, 4)', foo.mul3(2, 3, 4)) --> 24 -- . print('foo(2, 3)', foo(2, 3)) --> 6 foo.default = foo.mul3 print('Default was changed') print('foo(2, 3, 4)', foo(2, 3, 4)) --> 24
1.ã¡ã¿ããŒãã«ã®äœ¿çšäŸãšããŠãããŒãã«ãé¢æ°ãšããŠåŒã³åºãããšãã§ããŸãã é¢æ°ãšããŠåŒã³åºãããããŒãã«èªäœã¯ãselfãšããŠæž¡ãããŸãã
2.ãã®äŸã§ã¯ãããŒãã«ã«é¢æ°ãå ¥åããŸããã¡ã¿ããŒãã«ã¯ãé¢æ°ãšããŠåŒã³åºãããå Žåãããã©ã«ãããŒã®äžã§é¢æ°ã®çµæãè¿ãããšã瀺ããŸãã
ãã¹ããªã³ã°ãšé£çµ
ãªããžã§ã¯ããæååã«ãã£ã¹ãããŠé£çµããã ãã§ãã
mt = {} function mt.__tostring(self) return '['..table.concat(self, ', ')..']' end foo = setmetatable({}, mt) foo[1] = 10 foo[2] = 20 foo[3] = 30 print('foo', foo) --> [10, 20, 30] -- print('foo..foo', foo..foo) -- ! ! function mt.__concat(a, b) return tostring(a)..tostring(b) end print('foo.."!"', foo.."!") --> [10, 20, 30]! print('"!"..foo', "!"..foo) --> ![10, 20, 30] print('foo..foo', foo..foo) --> [10, 20, 30][10, 20, 30]
ã¡ã¿ããŒãã«
ã¡ã¿ããŒãã«ãé衚瀺ã«ãããšäŸ¿å©ãªå ŽåããããŸãã
mt = {} mt.id = 12345 foo = setmetatable({}, mt) print(getmetatable(foo).id) --> 12345 mt.__metatable = 'No metatables here!' print(getmetatable(foo)) --> 'No metatables here!' mt.__metatable = false print(getmetatable(foo)) --> false
ã¢ãŒã
æååãããŒãã«å€éã®é¢ä¿ã®ã¢ãŒãã瀺ããŸãã æå 'k'ãå«ãŸããŠããå ŽåãããŒã¯åŒ±ããšå®£èšãããæå 'v'ãå«ãŸããŠããå Žåãå€ã¯åŒ±ããšå®£èšãããŸãã ããããäžç·ã«äœ¿çšã§ããŸãã äŸã§ã¯collectgarbageé¢æ°ã䜿çšããŸã-ãã¹ãŠã®ã¬ããŒãžã匷å¶çã«åéããŸãã
Luaã®ããŒãã«-åžžã«åç §æž¡ãã
--[[1]] mt = {__mode = 'v'} foo = setmetatable({}, mt) --[[2]] bar = {foobar = 'fu'} foo.key = bar foo.key2 = {barfoo = 'uf'} foo[1] = 100500 --[[3]] print('foo.key.foobar', foo.key.foobar) --> 'fu' print('foo.key2.barfoo', foo.key2.barfoo) --> 'uf' print('foo[1]', foo[1]) --> 100500 collectgarbage() print('foo.key.foobar', foo.key.foobar) --> 'fu' print('foo[1]', foo[1]) --> 100500 -- print('foo.key2.barfoo', foo.key2.barfoo) --> , key2 ! --[[4]] bar = nil collectgarbage() -- print('foo.key.foobar', foo.key.foobar) --> , key !
1.匱ãå€ã®ããŒãã«ã®äŸïŒãã®ããŒãã«ãé€ããå€ãžã®åç §ããªãå Žåããããã¯ã¬ããŒãžã³ã¬ã¯ã·ã§ã³äžã«åé€ãããŸãã
2.ãã®ã³ãŒãã»ã¯ã·ã§ã³ã®å®è¡åŸãããŒãã«ãž
ã{foobar = 'fu'}ãã«ã¯ã2ã€ã®åç §ïŒã°ããŒãã«ã¹ããŒã¹ãšããŒãã«fooïŒãããã³ããŒãã«ãžã®åç §ããããŸãã
ã{barfoo = 'uf'}ãã¯ãfooã®äžã«ãããŸãã
3. fooããŒãã«ã«ã¯ãã¹ãŠã®å€ããããŸãããã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã®åŸãkey2ããŒãã«ãæ¶ããŠããããšãããããŸãã ããã¯ããããžã®åŒ·åãªãªã³ã¯ããªããªããã¬ããŒãžã³ã¬ã¯ã¿ãŒããããåéã§ãã匱ããªã³ã¯ã®ã¿ãååšããããã§ãã ããã¯foo [1]ã«ã¯é©çšãããŸããã100500ã¯åç §åã§ã¯ãªãããã§ãïŒããŒãã«ã§ã¯ãªããé¢æ°ã§ãããŠãŒã¶ãŒããŒã¿ãªã©ã§ããæ°åã§ã¯ãããŸããïŒã
4.å¯äžã®åŒ·åãªãªã³ã¯ããŒãåé€ãããšãã¬ããŒãžã³ã¬ã¯ã·ã§ã³åŸã«ããŒãã«{foobar = 'fu'}ãç Žæ£ãããŸãã
ããŒãã«åç §ããŒïŒfoo [{key = 'value'}] = trueïŒã«é¢ããŠã®ã¿ã 'k'ã§ãåæ§ã«æ©èœããŸãã
Gc
ããŒãã«ãã¬ããŒãžã³ã¬ã¯ã¿ãŒã«ãã£ãŠåéããããšã__ gcé¢æ°ãåŒã³åºãããŸãã ãã¡ã€ãã©ã€ã¶ãŒãšããŠäœ¿çšã§ããŸãã ããŒãã«ãšcdata / userdataãæã€é¢æ°ã
mt = {} function mt.__gc(self) print('Table '..tostring(self)..' has been destroyed!') end -- lua 5.2+ foo = {} setmetatable(foo, mt) -- Lua 5.1 if _VERSION == 'Lua 5.1' then -- __gc 5.1 cdata-. -- - , . -- 'foo', local t = foo -- newproxy cdata-, Lua 5.1. local proxy = newproxy(true) -- __gc cdata - __gc- foo getmetatable(proxy).__gc = function(self) mt.__gc(t) end foo[proxy] = true end print(foo) foo = nil collectgarbage() --> 'Table 0x12345678 has been destroyed!'
ã¬ã³
ããŒãã«ã®é·ããèšç®ããããã®ã¢ã«ãŽãªãºã ããªãŒããŒã©ã€ãããé¢æ°ïŒLua 5.2+ïŒã
mt = {} function mt.__len(self) local keys = 0 for k, v in pairs(self) do keys = keys + 1 end return keys end foo = setmetatable({}, mt) foo[1] = 10 foo[2] = 20 foo.key = 'value' print('#foo', #foo) --> 3 (2 Lua 5.1)
ãã¢ãšãã¢
ç¹å®ã®ããŒãã«ã®æšæºããŒãã«ã€ãã¬ãŒã¿ããªãŒããŒã©ã€ãããïŒLua 5.2+ïŒã
mt = {} function mt.__pairs(self) local key, value = next(self) return function() key, value = next(self, key) -- - . while key and type(key) == 'number' do key, value = next(self, key) end return key, value end end function mt.__ipairs(self) local i = 0 -- ipairs . return function() i = i - 1 return self[i] and i, self[i] end end foo = setmetatable({}, mt) foo[1] = 10 foo[2] = 20 foo[-1] = -10 foo[-2] = -20 foo.foo = 'foobar' foo.bar = 'barfoo' -- Lua 5.1 , -- 5.2+ - for k, v in pairs(foo) do print('pairs test', k, v) end --> foo foobar --> bar barfoo -- Lua 5.1 , -- 5.2+ - for i, v in ipairs(foo) do print('ipairs test', i, v) end --> -1 -10 --> -2 -20
ãªãã¬ãŒã¿ãŒã®éè² è·
ãã¹ãŠã®æŒç®åã®ãªãŒããŒããŒãã¯1ã€ã®ã¹ããŒã ã«åŸã£ãŠæ©èœããããããã®è©³çŽ°ãªäŸã¯å¿ èŠãããŸããã
]] --[[1]] vector_mt = {} function vector_mt.__add(a, b) local v = {} vx = ax + bx vy = ay + by return setmetatable(v, vector_mt) end function vector_mt.__div(a, b) local v = {} vx = ax / bx vy = ay / by return setmetatable(v, vector_mt) end -- function vector_mt.__tostring(self) return '['..self.x..', '..self.y..']' end vec1 = setmetatable({}, vector_mt) vec1.x = 1 vec1.y = 2 vec2 = setmetatable({}, vector_mt) vec2.x = 3 vec2.y = 4 vec3 = vec1 + vec2 print('vec3', vec3) --> [4, 6] print('vec2 / vec1', vec2 / vec1) --> [3, 2] --[[2]] mt = {} function mt.__add(a, b) local insert_position = 1 if type(a) == 'table' and getmetatable(a) == mt then insert_position = #a + 1 else a, b = b, a end table.insert(a, insert_position, b) return a end -- function mt.__tostring(self) return '['..table.concat(self, ', ')..']' end foo = setmetatable({}, mt) --[[3]] foo = 3 + 4 + foo + 10 + 20 + 'a' + 'b' print('foo', foo) --> [7, 10, 20, a, b] foo = '12345' + foo print('foo', foo) --> [12345, 7, 10, 20, a, b]
1.ã¡ã¿ããŒãã«ã®ãããã§ããã¯ãã«ã®ããã«æ¯ãèãããŒãã«ã§ã®æŒç®åã®ãªãŒããŒããŒãã®äŸã åŒæ°ã®é åºã«åŸãå¿ èŠããããåæäœã¯æ°ããããŒãã«-ããã¯ã¿ãŒããè¿ããŸãã
2.ã+ãæŒç®åã䜿çšããŠèŠçŽ ãè¿œå ã§ããè¡šã
è¿œå ã®é åºã¯ãèŠçŽ ãæ«å°Ÿã«è¿œå ãããå é ã«è¿œå ãããã決å®ããŸãã
3. 3 + 4ãæåã«å®è¡ããããããæåã®èŠçŽ ã¯ã7ãã§ãã
ãã®ä»ã®å Žåãåã®èŠçŽ ã®çµæã«æ¬¡ãè¿œå ãããŸãã
ïŒïŒ7 + foo-> fooïŒ+ 10-> fooïŒ...
ããããã¹ãŠã§äœãã§ããã§ããããïŒ
OOP
æåã«é Œãã®ã¯ãOOPãäœæããè©Šã¿ã§ãã
ããã€ãã®æœè±¡çãªãã¯ã©ã¹ããå®è£ ããåçŽãªé¢æ°ãäœæããŠã¿ãŸãããã
function Class() local class = {} -- . local mClass = {__index = class} -- , "" . function class.instance() return setmetatable({}, mClass) end return class end -- . Rectangle = Class() function Rectangle.new(x, y, w, h) local self = Rectangle.instance() self.x = x or 0 self.y = y or 0 self.w = w or 10 self.h = h or 10 return self end function Rectangle.area(self) return self.w * self.h end -- rect = Rectangle.new(10, 20, 30, 40) print('rect.area(rect)', rect.area(rect)) --> 1200 print('rect:area()', rect:area()) --> 1200
ããã§ã¯ããã§ã«OOPã«äŒŒãŠããŸãã ç¶æ¿ãããããçš®é¡ã®ã¯ãŒã«ãªãã®ã¯ãããŸããããããã¯æªããããŸããã
rect.areaãåŒã³åºããšãããªããžã§ã¯ãããŒãã«ã«ã¯ãšãªã¢ããŒããªããããã¯ã©ã¹ããŒãã«ã®__indexãä»ããŠæ€çŽ¢ãããããèŠã€ããŠãããã§æåã®åŒæ°ã«çœ®ãæããŸãã
ã¡ã¿ããŒãã«ããã®å°ããªäœè«ïŒ2åç®ã®åŒã³åºãã®äŸã¯ããã®èšäºã®æåã®ã³ãã³ã®åºçŸã§ãã ã³ãã³ã¯ãLuaèšèªã®æ§æç³è¡£ã§ãã ããŒãã«å ã®é¢æ°ãããªãªãã§ã¯ãªãã³ãã³ã§åŒã³åºãå ŽåãããŒãã«èªäœããã®é¢æ°ã®æåã®åŒæ°ãšããŠçœ®æãããããããã®ã³ãŒãã¯åçã§ãã
詳现ïŒ
foo = {x = 10, y = 20} function foo.bar(self, a, b) return (self.x + a) * (self.y + b) end print('foo.bar(foo, 1, 2)', foo.bar(foo, 1, 2)) --> 242 -- , self "" . function foo:bar(a, b) return (self.x + a) * (self.y + b) end print('foo:bar(1, 2)', foo:bar(1, 2)) --> 242
ãã®ãªãã·ã§ã³ãå°ãæ¹åããŠã¿ãŠãã ããã
ãŸãããªããžã§ã¯ããè¿ãé¢æ°ãšããŠã¯ã©ã¹ãåŒã³åºãæ©èœãè¿œå ããŸãã次ã«ãã¯ã©ã¹èªäœã®æŒç®åããªãŒããŒããŒãããæ©èœãè¿œå ããŸãã第äžã«ãç¶æ¿ã§ãã
function Class(parent) local class = {} local mClass = {} -- . -- . class.__index = class -- __index, -- , , . mClass.__index = parent -- Super . class.Super = parent -- , function mClass:__call(...) local instance = setmetatable({}, class) -- "init" if type(class.init) == 'function' then -- init return instance, instance:init(...) end -- - . return instance end return setmetatable(class, mClass) end -- . Shape = Class() function Shape:init(x, y) -- self . self.x = x or 0 self.y = y or 0 return '!!!' end function Shape:posArea() return self.x * self.y end -- Shape , -- . function Shape:__tostring() return '[' .. self.x .. ', ' .. self.y ..']' end local foo, value = Shape(10, 20) print('foo, value', foo, value) --> [10, 20] !!! -- Rectangle = Class(Shape) function Rectangle:init(x, y, w, h) -- , self - , -- Rectangle, . -- Super. self.Super.init(self, x, y) -- - . self.w, self.h = self:getDefault(w, h) end function Rectangle:area() return self.w * self.h end function Rectangle:getDefault(w, h) return w or 10, h or 20 end function Rectangle:__tostring() return '['..self.x..', '..self.y..', '..self.w .. ', '..self.h..']' end rect = Rectangle(10, 20, 30, 40) print('rect', rect) --> [10, 20, 30, 40] print('rect:area()' , rect:area()) --> 30 * 40 = 1200 -- print('rect:posArea()', rect:posArea()) --> 10 * 20 = 200
ãããã£ãŠã15è¡ã®äŸ¿å©ãªã³ãŒãã§ãæ¬åœã«å¿ èŠãªOOPã®æ倧å€ãLuaã«å®è£ ã§ããŸãã
ãã¡ãããæ¹åãã¹ãç¹ãšãããéã¿ä»ãããæ¹æ³ããããåæ§ã®äœæ¥ãmiddleclassãŸãã¯hump.Classã©ã€ãã©ãªã§è¡ãããŸããããããã圹ç«ã€å ŽåããããŸãã
ã¡ãªã¿ã«ãã¯ã©ã¹é¢æ°ã«ç ©ããããããªããã1ã€ãŸãã¯2ã€ã®ã¯ã©ã¹ãèšè¿°ããã ãã§ããå Žåã¯ããããããã¶ã€ã³ã䜿çšã§ããŸãã
ãããã·ããŒãã«
æåŸã«ãã¢ã¯ãã£ããã£ãã©ããã³ã°ãåããæ¬æ Œçãªãããã·ã®äŸã瀺ããŸãã
function proxy() local real_table = {} local logger = {} local metatable = {} -- function metatable:__index(key) local value = rawget(real_table, key) table.insert(logger, "Get key "..tostring(key)..' is '.. tostring(value)) return value end -- , function metatable:__newindex(key, value) table.insert(logger, "Set key "..tostring(key)..' as '..tostring(value)) rawset(real_table, key, value) end return setmetatable({}, metatable), logger end prox, log = proxy() prox.a = 10 prox.a = 20 print('prox.a', prox.a) --> 20 print('log', '\n'..table.concat(log, '\n')) --> Set key a as 10 --> Set key a as 20 --> Get key a, is 20
åºåã¯ããã®äœ¿çšãèšé²ããããŒãã«ã§ãã ãã®å Žåããããã·ããŒãã«ã¯åžžã«ç©ºã§ãããŒãååšããªããããæ¯å__newindexãåŒã³åºãããŸãã
äžæãªããžã§ã¯ãããŒãã«
äžæçã«ååšããäžæãªããžã§ã¯ããå¿ èŠã«ãªãå ŽåããããŸãããååãªã¡ã¢ãªããªãå Žåã¯ç©ºãé åãå¢ããŸãã ãã®äŸã§ã¯Luasecã©ã€ãã©ãªïŒhttpsãªã¯ãšã¹ãïŒãå¿ èŠã«ãªããŸããã Luasocketã䜿çšããŠãåãæåãåŸãããŸãããhttpsãå¿ èŠã§ãã
page = {} page.https = require'ssl.https' page.cache = setmetatable({}, {__mode = 'v'}) -- page._meta = {} function page._meta:__tostring() return 'Page: ['..self.url.. ']: '.. self.status end setmetatable(page, page) function page:__call(url) return self.cache[url] or self:request(url) end function page:request(url) local page = setmetatable({}, self._meta) page.url = url page.data, page.status, page.error, page.hate = self.https.request(url) print(page.data, page.status, page.error, page.hate) self.cache[url] = page return page end -- , , . p = page('https://yandex.ru') print('p', p) --> Page: [https://yandex.ru]: 200 print('p.status', p.status) --> 200 -- , -- - . print('page.cache[...]', page.cache['https://yandex.ru']) --> Page: [https://yandex.ru]: 200 -- , "p". collectgarbage() print('page.cache[...]', page.cache['https://yandex.ru']) --> Page: [https://yandex.ru]: 200 p = nil collectgarbage() -- - , . print('page.cache[...]', page.cache['https://yandex.ru']) --> Nil
ä»ã®ãšãã
ãããããäŸãé¢çœãäŸãããã°ããã®è³æã¯å€ããå°ãªãããã¹ã¿ãŒã¡ã¿ããŒãã«ã«ååã ãšæããŸã-ã³ã¡ã³ãã«æžããŠãã ããã
ããããã®è³ªåãããã人ã®ããã«- ã«ãŒãã«ãã£ããã«ãŒã ãžã®ãªã³ã¯ãæ®ããŠãã ããã