Hello! Welcome to my tutorial about Lua Metatables. Let’s begin!
What is a metatable
I recommend thinking of metatables as more powerful tables. With a lot more operations
compared to a normal table, like arithmetic, tostring, and more!
Image by @BenSBk
How do you set a metatable to a table
To set a metatable to a table, we’ll use setmetatable()
.
It requires 2 arguments: The table you want to attach the metatable to, and the metatable.
Example code:
local normalTable = {};
local metametable = {};
setmetatable(normalTable, metamethod)
Know that putting setmetatable()
in a variable returns the table that you wanted to attach the metatable to. Example:
local meta = setmetatable({Lol = 15}, {}) -- Returns the first argument (the table you want to attach the metatable to.)
print(meta.Lol) -- Prints 15
Metamethods and how you set them
You can think of metamethods just like events! In Roblox, whenever you have a part for example, and you detect .Touched
event, it of course fires each time the part is touched, so, metamethods invoke whenever something happens in the table. Like indexing a key that does not exist (__index)
, trying to change a value of a key that does not exist (__newindex)
, etc. Metamethods have 2 underscores before their metamethod’s name, always remember to put them: __
How do you set a metamethod to the metatable?
Example code:
local normalTable = {};
local metatable = {} -- Metatables are normal tables, with metamethods inside.
metatable.__index = function(tab, key)
return key.. " was not found in table."
end
setmetatable(normalTable, metatable)
You can also retrun a table, so, if the metamethod invokes,
it does a ‘re-check’ on table that you return. Example:
local normalTable = {};
local metatable = {}
metatable.__index = {Value = 5} -- Returns this table and does a 're-check' on it.
setmetatable(normalTable, metatable)
print(normalTable.Value) -- Prints 5, as it exists in the table that we returned.
When each metamethod invokes
You’ll mostly be using the
__index
and __newindex
metamethods, others for specific cases.
(The metamethods chart can be found here)
What is getmetatable()?
As I reminded in the code above, when you put setmetatable()
in a variable, it returns the first argument (the table). Now, how can you get the metatable? You will use getmetatable()
.
Example code:
local normalTable = {};
local meta = setmetatable(normalTable, {})
local metatable = getmetatable(meta) -- Returns the second argument (the metatable).
metatable.__index = function(tab, key) -- Adding the metamethod to the metatable.
return key -- Instead of returning nil, it returns the key that was tried to index.
end
print(normalTable.lol) -- Prints lol!
Another example:
local normalTable = {Username = "XDvvvDX"};
local meta = setmetatable(normalTable, {});
local metatable = getmetatable(meta); -- Returns the second argument (the metatable).
metatable.__tostring = function(tab) -- __tostring returns the table.
return tab.Username
end
print(tostring(normalTable)) -- Prints XDvvvDX!
Userdatas & Proxies
Instead of using setmetatable()
, you can use userdatas.
Userdatas are used mostly to bypass metamethods that are not supported
by the version of Lua that Roblox is using (try to print _VERSION
).
You’ll use newproxy()
, which creates a new proxy, and then
you can get it’s metatable using getmetatable()
.
Example code:
local userData = newproxy(true); -- Setting it to true so it's metatable is editable.
local metatable = getmetatable(userData) -- Getting the metatable.
metatable.__len = function(tab) -- The __len metamethod isn't supported.
return math.pi
end
print(#userData) -- Prints the value of pi!
Use cases of metatables
Metatables are especially used in Oriented Object Programming, and it is very important
to understand before dealing with Oriented Object Programming.
Recommended sources to learn metatables from
If you read this post until the end, and did not understand metatable still, I recommend looking at these sources that may help you:
Metatables explanation by ScriptGuider
Metatables explanation by AlvinBlox
Metatables community tutorial by @starmaq
If you have any questions or mistakes you’ve found in my post, feel free to ask in the comment section of this post. Thank you!