Skip to content

Instantly share code, notes, and snippets.

@Deco
Created February 2, 2012 08:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save Deco/1722294 to your computer and use it in GitHub Desktop.
Save Deco/1722294 to your computer and use it in GitHub Desktop.
Luvit module example (using _G)
require"oo"
geometry = {}
do geometry.Shape = OO.class({
})
function geometry.Shape:__init()
error("attempt to instantiate abstract shape")
end
end
do geometry.Rectangle = OO.class(geometry.Shape, {
x = 0, y = 0,
w = 0, h = 0,
})
function geometry.Rectangle:__init(x, y, w, h)
return setmetatable({
x = tonumber(x), y = tonumber(y),
w = tonumber(w), h = tonumber(h),
}, self)
end
function geometry.Rectangle:getArea()
return math.sqrt(self.w^2+self.h^2)
end
end
do geometry.Circle = OO.class(geometry.Circle, {
--userdata = newproxy(),
radius = 0,
})
function geometry.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 geometry.Circle:getArea(obj)
return math.pi*self.radius^2
end
end
function geometry.spawnCircle(radius) -- let's assume Circles are like processes
return geometry.Circle{
userdata = newproxy(), -- UV.get_circle
radius = radius
}
end
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
OO = {}
do --OO.class
local function class_new(self, ...)
return setmetatable(self.__init and self:__init(...) or {}, self)
end
OO.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 OO.classof
= debug.getmetatable -- hopefully this aliasing doesn't mess up the fast function optimisation
end
do OO.instanceof
= function(instance, class)
return debug.getmetatable(instance)[class]
end
end
do OO.supersof
= function(class)
return debug.getmetatable(class).__supers
end
end
do OO.supersofinstance -- == supersof(classof(instance))
= function(instance)
return debug.getmetatable(debug.getmetatable(instance)).__supers
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment