I consistently see people using this thing called metatables
and see a lot of __
This is an example of what I've seen:
local tab = {} setmetatable(tab, tabl)
Just like the title says: What are metatables, what is their use and why should I use them?
All help is appreciated!
Well so i am not pro at metatables, but i know some good uses for them, it is used a lot for Object Oriented Programming.
So to create a metatable as you said you use setmetatable()
function, but first you need to have 2 tables, one you want to set metatable to and one handling the metatable functions, i will explain here so you won't be that confused.
So for example you have a table:
local myTable = {}
And you want to add value in it, you would do this:
myTable["myValue"] = 5
But let's say you also want to do a specific function when adding the value instead of just putting the number in it, you want to do more stuff for example. Here is when you can use metatable, those __ are built in functions that you can use, here are some of them and how you can use them.
So first you need to make a new table which will be our metatable
local metatable = {}
And now here are the functions:
[EDIT: You can later find them on the devforum instead of this mess]
__index(table, index) Fires when table[index] is indexed, if table[index] is nil. Can also be set to a table, in which case that table will be indexed.
__newindex(table, index, value) Fires when table[index] tries to be set (table[index] = value), if table[index] is nil. Can also be set to a table, in which case that table will be indexed.
__call(table, ...) Fires when the table is called like a function, ... is the arguments that were passed.
__concat(table, value) Fires when the .. concatenation operator is used on the table.
__unm(table) Fires when the unary – operator is used on the table.
__add(table, value) The + addition operator.
__sub(table, value) The – subtraction operator.
__mul(table, value) The * mulitplication operator.
__div(table, value) The / division operator.
__mod(table, value) The % modulus operator.
__pow(table, value) The ^ exponentiation operator.
__tostring(table) Fired when tostring is called on the table.
__metatable if present, locks the metatable so getmetatable will return this instead of the metatable and setmetatable will error. Non-function value.
__eq(table, value) The == equal to operator¹
__lt(table, value) The < less than operator¹; NOTE: Using the >= greater than or equal to operator will invoke this metamethod and return the opposite of what this returns, as greater than or equal to is the same as not less than.
__le(table, value) The <= operator¹; NOTE: Using the > greater than operator will invoke this metamethod and return the opposite of what this returns, as greater than is the same as not less than or equal to.
__mode Used in weak tables, declaring whether the keys and/or values of a table are weak. NOTE: References to Roblox instances are never weak. Tables that hold such references will never be garbage collected.
__gc(table) Fired when the table is garbage-collected. NOTE: On Roblox, this metamethod is disabled.
__len(table) Fired when the # length operator is used on the Object. NOTE: Only userdatas actually respect the __len() metamethod in Lua 5.1.
This is just stolen from the devforum page
But here is explanation of how it works:
To create a function like that you need to take the metatable:
local myMetatable = {} function myMetatable:__newindex() print("metatable has been newindexed!") end function myMetatable:__index() print("__index has been used!") end
So you don't know now what is it BUT the output will explain this very quickly
So first let's set the metatable
setmetatable(myTable, myMetatable)
And now here it comes
print(myTable["car"])
So this is when the __index function that we put into the metatable fires, whenever the table is indexed, and we attached function to it which prints it so the output will be:
2:00:00 > __index has been used!
This is same just like __newindex and most of the other __ functions works. So let's use __newindex since we put it into the metatable too! It fires whenever the table is indexed with a value like this:
myTable["car"] = true --Output 2:00:00 > myTable has been newindexed!
ASAIK instead of adding the ["car"] value into the table, it will fire the function so if you print it:
myTable["car"] = true print(myTable['car'])
Output should be:
2:00:00 > myTable has been newindexed! 2:00:00 > nil -- Because instead it fired the function
And you can attach also other functions like __add function which will fire whenever you do
+myTable
Although you will need to have other arguments there. So for example:
print( 5 + myTable)
This is when it won't error and it will fire the __add function.
You can create mutliple tables like that:
local function CreateTable() return setmetatable({}, myMetatable) end local myNewTable = CreateTable() myNewTable['car'] = true --Output 2:00:00 > myTable has been newindexed!
Also i didn't say but here are what the arguments are for it:
myNewTable['car'] = true
function myMetatable:__index( -- First argument is the index, in this case it's 'car' -- Second argument is the value given, in this case it would be 'true' )
Since i used :
, then the self is automatically defined, if you use .
then it's
function myMetatable.__index( -- Self, -- 'Car', -- 'true' )
Those were the basics, this is just how i use it, i am not explaining it that good but i think something is understandable, here are some sources you could use: