---Declare table as a base class ---@generic T ---@param cls T # class metatable ---@param o? table # initial parameters ---@return T # class instance function Base(cls, o) o = o or {} cls.__index = cls setmetatable(o, cls) return o end local function search(key, bases) for _, base in ipairs(bases) do local v = base[key] -- try `i'-th superclass if v then return v end end end ---Declare table as a derived class ---@generic BaseT, T ---@param cls T # class metatable ---@param o? table # initial parameters ---@param ... BaseT # base class metatables ---@return T # derived class instance function Inherit(cls, o, ...) o = o or {} local nargs = select("#", ...) local vargs = { select(1, ...) } cls.__index = cls if nargs > 1 then setmetatable(cls, {__index = function(t, k) return search(k, vargs) end}) for _, base in ipairs(vargs) do o = base:new(o) end else local base = assert(vargs[1], "You must at least specify one class to inherit from.") setmetatable(cls, {__index = base}) o = base:new(o) end setmetatable(o, cls) return o end