I know this is a several-month-old reply but I still want to provide some optimizations because you’re using a lot of extra checks:
local myObject = {}
-- we should define class functions as a member of myObject
function myObject:Random()
return math.random()
end
function myObject:Destroy()
self._extends:Destroy()
setmetatable(self, nil)
-- set any extra non-gc'able properties to nil here
end
-- we should set metamethods inside that table as well:
function myObject:__index(newKey)
if myObject[newKey] then
return myObject[newKey] -- this will not invoke the __index metamethod since we're indexing the metatable, not the actual table
elseif type(myObject._extends[newKey]) == 'function' then -- this will not error since newKey is either a member function or a property
return function(_, ...)
return myObject._extends[newKey](myObject._extends, ...)
end
end
return myObject._extends[newKey] -- it cannot be anything but a property at this point, if it is, it will error correctly
end
function myObject:__index(key, value) -- this will only fire when attempting to add a new value to the wrapped object
self._extends[key] = value
end
function myObject.new(myInstance) -- if the instance doesn't exist yet, you can create it here
local newObject = {}
newObject.cool = true -- we want to define properties inside the object, we do not want to define functions in the object's table.
newObject._extends = myInstance
return setmetatable(newObject, myObject)
end