Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
4

Problem with metatables and workspace?

Asked by 9 years ago

So I'm having trouble with this bit of code. I'm trying to make a metatable with it's __index metamethod referencing the Workspaceservice. I'm doing this to create custom methods on workspace, while at the same time keeping all it's other properties / methods accessible with the metatable.

Here's what I have:

01-- _workspace is the table of custom methods
02local _workspace = {}
03 
04-- custom "GetName" method
05function _workspace:GetName()
06    return "Hello, I'm the workspace"
07end
08 
09-- Here I overwrite the global "workspace" variable, with a table containing custom methods, but a metatable referring to it's original self.
10local workspace = setmetatable(_workspace,{
11    __index = workspace
12})
13 
14-- Now if I said...
15print(workspace:GetName()) -- It prints "Hello, I'm the workspace"
16 
17-- However... If I were to use a default method like GetChildren...
18print(workspace:GetChildren())
19 
20-- It errors.

The problem?

So calling my custom method on the new overwritten "workspace" variable works, but it seems to cause an error for every other single method that already existed on the workspace.

Here's the error I get when I call something like "GetChildren" on the workspace after applying my code:

19:02:38.753 - Expected ':' not '.' calling member function GetChildren

Which is weird, because I do have the original workspace service referenced with the __index metamethod, and I am calling it with : , not .. So what's wrong?

If anyone out there can provide some insight on this, I'd be very grateful. It's been driving me crazy.

0
i dont think you can access or overwrite the environment of any of roblox's methods in which they reside such as findfirstchild or getchildren but i might be wrong 4Bros 550 — 9y
0
for instance: print(getmetatable(workspace)) and print(getmetatable(getfenv(workspace.FindFirstChild))) returns "The metatable is locked" 4Bros 550 — 9y
0
He's not modifying them. He's creating a metatable that references methods from them, while including custom ones. This is done with object wrappers all the time. ScriptGuider 5640 — 9y
0
I think I see the issue. I'm gonna test just in case. adark 5487 — 9y

1 answer

Log in to vote
5
Answered by
adark 5487 Badge of Merit Moderation Voter Community Moderator
9 years ago

Alright, this one's a bit tricky.

What's happening is workspace.GetChildren is expecting workspace as the first argument, and is instead getting your custom table, which is not what we want.

To fix this, we have to manually call the method of workspace we're trying to access:

01local _workspace = {}
02 
03function _workspace:GetName()
04    return "Hello, I'm the workspace"
05end
06 
07local ws = game:GetService("Workspace")
08local workspace = setmetatable(_workspace,{
09    __index = function(_, prop)
10        return function(_, ...) --This ignores the first argument to the __index'd function call: your _workspace table.
11            return ws[prop](ws, ...)
12        end
13    end;
14})
15 
16print(workspace:GetName())
17print(workspace:GetChildren())

There are two issues with this, though: accessing and setting properties of workspace is not possible via your Table!

To fix this, we have to change __index slightly and add a __newindex to track properties being set:

01local _workspace = {}
02 
03function _workspace:GetName()
04    return "Hello, I'm the workspace"
05end
06 
07local ws = game:GetService("Workspace")
08local workspace = setmetatable(_workspace,{
09    __index = function(_, prop)
10        if type(ws[prop]) == "function" then
11            return function(_, ...) --This ignores the first argument to the __index'd function call: your _workspace table.
12                return ws[prop](ws, ...)
13            end
14        else --Correctly return properties
15            return ws[prop]
View all 30 lines...

There are a few issues with this, namely properties that have an initial nil value, but that's beyond the scope of this answer.

0
Thank you very much, this makes total sense! Accepted and upvoted. MightyQuestionAsker 297 — 9y
Ad

Answer this question