Skip to content

Instantly share code, notes, and snippets.

@Deco
Forked from Deco/geometry.lua
Created February 2, 2012 08:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Deco/1722329 to your computer and use it in GitHub Desktop.
Save Deco/1722329 to your computer and use it in GitHub Desktop.
Luvit module example (using local _M table) (my personal choice)
local OO = require"oo"
local _M = {}
do _M.Shape = OO.class({
})
function _M.Shape:__init()
error("attempt to instantiate abstract shape")
end
end
do _M.Rectangle = OO.class(_M.Shape, {
x = 0, y = 0,
w = 0, h = 0,
})
function _M.Rectangle:__init(x, y, w, h)
return setmetatable({
x = tonumber(x), y = tonumber(y),
w = tonumber(w), h = tonumber(h),
}, self)
end
function _M.Rectangle:getArea()
return math.sqrt(self.w^2+self.h^2)
end
end
do _M.Circle = OO.class(_M.Shape, {
--userdata = newproxy(),
radius = 0,
})
function _M.Circle:__init(obj)
assert(type(obj.userdata) == "userdata", "attempt to construct Circle with invalid userdata")
-- the only reason setmetatable is preformed manually is that in the game engine I use it in I
-- use classes on userdata (created with newproxy). For these, debug.setmetatable must be called.
-- Hence, I never forced setmetatable to be used on the object internally.
return setmetatable(obj, self)
end
function _M.Circle:getArea(obj)
return math.pi*self.radius^2
end
end
function _M.spawnCircle(radius) -- let's assume Circles are like processes
return _M.Circle{
userdata = newproxy(), -- UV.get_circle
radius = radius
}
end
return _M
require"oo"
require"geometry"
local rect = geometry.Rectangle(0, 0, 3, 4)
print(rect:getArea(), OO.instanceof(rect, geometry.Shape)) -- 5 true
local circ = geometry.spawnCircle(2)
print(circ:getArea()) -- 12.566370614359
local setmetatable = setmetatable
local table, debug = table, debug
local _M = {}
do --class
local function class_new(self, ...)
return setmetatable(self.__init and self:__init(...) or {}, self)
end
_M.class = function(...)
local supers = {...}
local class = table.remove(supers, #supers)
class.__index = (
class.__index ~= nil and class.__index
or class.__index_def and class.__index_def(class)
or class
)
class[class] = true
local supers_len = #supers -- hopefully this will help LuaJIT unroll the loop statically
return setmetatable(
class,
{
__supers = supers,
__class = class,
__call = class.__init or class_new,
__index = (
supers_len == 0 and nil
or supers_len == 1 and supers[1]
or function(self, key)
for super_i = 1, supers_len do
local value = supers[super_i][key]
if value then return value end
end
end
),
}
)
end
end
do _M.classof
= debug.getmetatable -- hopefully this aliasing doesn't mess up the fast function optimisation
end
do _M.instanceof
= function(instance, class)
return debug.getmetatable(instance)[class]
end
end
do _M.supersof
= function(class)
return debug.getmetatable(class).__supers
end
end
do _M.supersofinstance -- == supersof(classof(instance))
= function(instance)
return debug.getmetatable(debug.getmetatable(instance)).__supers
end
end
return _M
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment