That’s because you’re trying to call a workspace function on a table, to fix it you would have to wrap the actual instance method with another function like so:
local methods = {}
methods._extends = workspace -- the "original" instance, this would be constant throughout all of your workspace extensions but if your instance can vary, you will want to define this in your constructor below
function methods:__index(key)
-- remember 'self' is already defined
-- case 1, the function exists in the methods table
if methods[key] then
return methods[key]
else
-- save the member to a variable for readability
local member = methods._extends[key]
-- if your instance can vary and is defined per-object, do self._extends[key] instead of methods._extends[key]
if type(member) == 'function' then
-- case 2: the member is a function
return function(_, ...) -- _ in this case would be equal to self
return member(methods._extends, ...) -- remember to switch to self._extends if the real instance is per-object
end -- now, this function gets called when called which calls `member` with the proper arguments
end
-- case 3: the member is a property, return it
return member
end
end
function object.new() -- you can define 'arg' in here if you're passing a varying instance which gets defined per-object
local newObject = {}
-- if you are going to pass an object here to extend, you'd do something like
-- newObject._extends = arg
return setmetatable(newObject, methods)
end
Not quite, self isn’t defined here. self is just a variable really, it just gets defined automatically when a function is defined with a colon
local blocks = {
Grass = 10;
Gold = 20;
}
function blocks:GetGrass() -- remember, defining a function using a colon will assign `self` automatically, in this case, self is blocks
return self.Grass
end
-- also remember that the above function definition is the exact same as doing this:
function blocks.GetGrass(self)
return self.Grass
end
-- now, this will not error:
blocks:GetGrass()