Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- eoo.lua: Edrx'x simple OO scheme. -- Documentation: (find-dn6 "eoo.lua") -- (find-dn6 "eoo.lua" "__mt") -- -- This file: -- http://angg.twu.net/blogme4/eoo.lua.html -- http://angg.twu.net/blogme4/eoo.lua -- (find-blogme4file "eoo.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011jan12 -- License: GPL3 -- -- A very simple object system. -- The metatable of each object points to its class, -- and classes are callable, and act as creators. -- New classes can be created with, e.g.: -- Circle = Class { type = "Circle", __index = {...} } -- then: -- Circle {size = 1} -- sets the metatable of the table {size = 1} to Circle, -- and returns the table {size = 1} (with its mt modified). -- -- Originally from: (find-angg "LUA/canvas2.lua" "Class") -- A tool: (find-angg ".emacs.templates" "class") -- Inheritance: (find-dn5 "eoo.lua") -- Announcement: http://lua-users.org/lists/lua-l/2011-03/msg00975.html -- «.test-eoo» (to "test-eoo") Class = { type = "Class", __call = function (class, o) return setmetatable(o, class) end, } setmetatable(Class, Class) otype = function (o) -- works like type, except on my "objects" local mt = getmetatable(o) return mt and mt.type or type(o) end -- dump-to: tests -- «test-eoo» (to ".test-eoo") --[==[ -- Here is a detailed explanation of how this works. -- Using the notation of the __mt patch, at: -- http://angg.twu.net/__mt.html -- (find-TH "__mt") -- we can rewrite the code above as: -- Class = { type = "Class", -- __call = \ (class, o) => o.__mt = class end } -- Class.__mt = Class -- otype = \ (o) local mt = o.__mt; => mt and mt.type or type(o) end -- Here is a test for it (note: it does _not_ require a patched Lua). * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) ee_dofile "~/blogme4/eoo.lua" -- this file Vector = Class { type = "Vector", __add = function (V, W) return Vector {V[1]+W[1], V[2]+W[2]} end, __tostring = function (V) return "("..V[1]..","..V[2]..")" end, __index = { norm = function (V) return math.sqrt(V[1]^2 + V[2]^2) end, }, } v = Vector {3, 4} -- v = { 3, 4, __mt = Vector} w = Vector {20, 30} -- w = {20, 30, __mt = Vector} print(v) --> (3,4) print(v + w) --> (23,34) print(v:norm()) --> 5 print( type(v)) --> table print(otype(v)) --> Vector print( type("")) --> string print(otype("")) --> string -- So we have: -- -- Class = { -- type = "Class", -- __call = \(class, o) => o.__mt = class end, -- __mt = Class -- } -- Vector = { -- type = "Vector", -- __add = \(V, W) => {V[1]+W[1], V[2]+W[2]} end, -- __tostring = \(V) => "("..V[1]..","..V[2]..")" end, -- __index = { norm = \(V) => math.sqrt(V[1]^2+V[2]^2) end }, -- __mt = Class -- } -- -- and we can use reductions to understand "Vector {3, 4}" and "v:norm()": -- -- v = Vector {3, 4} -- --~-> Vector({3, 4}) -- --~-> Vector.__mt.__call(Vector, {3, 4}) -- --~-> Class.__call(Vector, {3, 4}) -- --~-> (\(class, o) => o.__mt = class end)(Vector, {3, 4}) -- --~-> (\() => {3, 4}.__mt = Vector end)() -- --~-> {3, 4, __mt = Vector} -- -- and: -- -- v:norm() -- --~-> {3, 4, __mt=Vector}:norm() -- --~-> {3, 4, __mt=Vector}.norm ({3, 4, __mt=Vector}) -- --~-> {3, 4, __mt=Vector}.__mt.__index.norm({3, 4, __mt=Vector}) -- --~-> Vector.__index.norm({3, 4, __mt=Vector}) -- --~-> (\(V) => math.sqrt(V[1]^2+V[2]^2) end)({3, 4, __mt=Vector}) -- --~-> (\() => math.sqrt( 3^2+ 4^2) end)() -- --~-> (\() => 5 end)() -- --~-> 5 -- --]==] -- Local Variables: -- coding: raw-text-unix -- ee-anchor-format: "«%s»" -- End: