So I'm having trouble with this bit of code. I'm trying to make a metatable
with it's __index
metamethod referencing the Workspace
service. 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 |
02 | local _workspace = { } |
03 |
04 | -- custom "GetName" method |
05 | function _workspace:GetName() |
06 | return "Hello, I'm the workspace" |
07 | end |
08 |
09 | -- Here I overwrite the global "workspace" variable, with a table containing custom methods, but a metatable referring to it's original self. |
10 | local workspace = setmetatable (_workspace, { |
11 | __index = workspace |
12 | } ) |
13 |
14 | -- Now if I said... |
15 | print (workspace:GetName()) -- It prints "Hello, I'm the workspace" |
16 |
17 | -- However... If I were to use a default method like GetChildren... |
18 | print (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.
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:
01 | local _workspace = { } |
02 |
03 | function _workspace:GetName() |
04 | return "Hello, I'm the workspace" |
05 | end |
06 |
07 | local ws = game:GetService( "Workspace" ) |
08 | local 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 |
16 | print (workspace:GetName()) |
17 | print (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:
01 | local _workspace = { } |
02 |
03 | function _workspace:GetName() |
04 | return "Hello, I'm the workspace" |
05 | end |
06 |
07 | local ws = game:GetService( "Workspace" ) |
08 | local 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 ] |
There are a few issues with this, namely properties that have an initial nil
value, but that's beyond the scope of this answer.