Wrapping objects and adding functionalities to them

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
2 Likes