Skip to content

Instantly share code, notes, and snippets.

@AlphaTechNinja
Created April 12, 2024 21:35
Show Gist options
  • Select an option

  • Save AlphaTechNinja/a757bd790b53d23f49df3bd78ab79ea6 to your computer and use it in GitHub Desktop.

Select an option

Save AlphaTechNinja/a757bd790b53d23f49df3bd78ab79ea6 to your computer and use it in GitHub Desktop.
A refined version of my class library (now supports multi class inheritance, search tree, and loading) WARNING: this is written for cc: tweaked (to make it compatible with other engines you will have to change the “fs library to match the ones of your program”)
--refined class library
local classes = {}
classes.__index = classes
classes.path = package.path
classes._tree = {}
classes.loaded = {}
local weakTab = {__mode = "k"}
local function multiclass(parents)
local fast = {}
setmetatable(fast,weakTab)
return function (k)
if fast[k] then
return fast[k]
end
--return function (k)
for _,parent in pairs(parents) do
if parent[k] then
fast[k] = parent[k]
return parent[k]
end
end
end
end
function classes.create(name,...)
local args = {...}
if #args == 0 then
local class = setmetatable({},classes)
class.__name = name
table.insert(classes._tree,class)
class.__index = class
return class
end
if #args < 2 then
local class = setmetatable({},args[1] or classes)
class.__name = name
table.insert(classes._tree,class)
class.__index = class
return class
end
local class = {}
class.__name = name
table.insert(classes._tree,class)
setmetatable(class,{__index = multiclass(args),__parents = args})
class.__index = class
return class
end
setmetatable(classes,{__call = function (_,...) return classes.create(...) end})
-- private allows addition specification of external methods
function classes.private(name,private,...)
local base = classes.create(name,...)
local old = getmetatable(base)
if type(old) == "function" then
setmetatable(base,{__index = function (_,k) local v = old(k) if v then return v else return private[k] end end})
else
setmetatable(base,{__index = multiclass(old,private)})
end
return base
end
--methods
function classes:new(...)
if self.constructor then
return self:constructor(...)
else
return setmetatable({...},self)
end
end
function classes:__call(...)
return self:new(...)
end
function classes:isOf(parent,direct)
if direct then
return getmetatable(self) == parent
elseif getmetatable(self).__parents then
else
if getmetatable(self) == parent then
return true
else
return getmetatable(self):isOf(parent)
end
end
end
--the tree allows classes to persist entire removed
function classes:remove()
for i,class in ipairs(classes._tree) do
if class == self then
table.remove(classes._tree,i)
return
end
end
end
function classes.getClass(name)
for i,class in ipairs(classes._tree) do
if class.__name == name then
return class
end
end
end
local env = {}
env.require = require
env.package = package
--load classes
function classes.loadClass(name,class)
--classes can be required seperate from standard require
--used to insert a class
if class then
assert(not classes.loaded[name],"class has already been defined")
classes.loaded[name] = class
return true
end
--normal
local errmsg = {}
local function err(str)
table.insert(errmsg,str)
end
err(("failed to load class '%s':"):format(name))
--check for class
if classes.loaded[name] then
return classes.loaded[name]
end
--search
--make name a normal path
local normal = name:gsub("%.","%/")
local found
for path in classes.path:gmatch("[^;]+") do
--substitute wild card
path = path:gsub("%?",normal)
if path:sub(1,1) == "/" then
--absolute path
if fs.exists(path) then
found = path
break
end
else
--relitive
--append relitive path
path = fs.combine(fs.getDir(shell.getRunningProgram()),path)
if fs.exists(path) then
found = path
break
end
end
--add to errors
err(("%s not found in %s"):format(name,path))
end
if found then
classes.loaded[name] = loadfile(found,setmetatable({},{__index = function (_,k) if _G[k] then return _G[k] else return env[k] end end}))(classes)
return classes.loaded[name]
end
error(table.concat(errmsg,"\n"),2)
end
return classes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment