What are metatables, in the simplest explanation please

Hey everyone, I am learning about modules I just learned what the use of self was used for in modules and now I want to understand what metatables were used for now in the simplest explanation, since I am a trying to understand scripting.

Metatables, you’ll come to find, are one of the coolest parts of Lua tables, and are super powerful. Once you learn how to use them, you’ll be able to get much more creative with your modules.

Firstly, I’ll link this article for you: Metatables | Roblox Creator Documentation

Okay, onto the explanation. Every lua table also has a metatable, think of it as a holder for specific properties. These properties are called metamethods.

Here is a lua table:

local myTable = {}

Currently, that table doesn’t have a metatable. You can set one with the global methods: setmetatable. This is how you’d use that:

setmetatable(MyTable, {})

The first argument is the table which you’re setting the metatable of. The second argument is the metatable itself–it’s just another lua table. (You can even set something’s metatable to itself, that is very common practice).

The useful part of a metatable, the only part that matters at least, are the metamethods. There is a full list of them in the developer hub article linked above.

The most commonly used metamethods is __index. What this does is it lets you manually handle indexing of your table. Let me give an example:

--You have two tables:
local table1 = {}
local table2 = {}

--Let's set some values:
table1.myValue = "foo"
table2.myValue = "bar"
table2.otherValue = "bar"

--Let's set up the metatable for table1:
table1.__index = table2
setmetatable(table1, table1) --We're setting table1's metatable to itself.
-- table1 has a __index, which is set to table2.
-- This means that when you index table1, if it cannot find the key, it will
-- then index table2 and if it finds a value, it will return that.

--Printing values:
print(table1.myValue) --Output: "foo"
-- Notice that it outputs "foo", even though table2 has that same key with a
-- value of "bar". It will only search through table2 if the key is not found
-- in table1.

print(table1.otherValue) --Output: "bar"
-- table1 does not have a value at the key "otherValue", so it checks through
-- table2 and finds the value, therefore it is returned. This would not happen
-- if it weren't for the metatable. It would just output nil.

The article linked above has explanations for all of the metamethods, so you can reference that for the rest of them. Keep a few things in mind as you do: you can assign functions to all of the metamethods, and it’ll use whatever that function returns. This is explained more in the article. Also, a table’s metatable can be any table, it does not have to be itself, and you can create the table in the setmetatable call like so:

local myTable = {}
setmetatable(myTable, {__index = myTable})

Also, one last thing of note. I have found that this is the most common declaration in module constructors:

local function myModule.new()
	local self = setmetatable({}, 
		{
			__index = myModule
		}
	)
end

(This works because setmetatable returns the table passed in as the first argument)

If you have any follow-up questions, or if you’d like to me to explain anything again (more simply, or more complex-ly) feel free to ask away!

2 Likes

So in the most simplest explanation, metatables are basically used whenever the script requests to find something in the first table, only if it doesn’t have that data the script requested.

That’s only one part of it. Metatables are basically used to give tables specific functionality. If you look through the article I linked you’ll see other metamethods with different functionality. They allow you to overload operators too, which basically means you can give it custom functionality for when you you try to perform math operations on it. You can also use a metamethods to set what happens when something tries to convert the table into a string, so you can have a function that packages up the information so that it can be printed nicely, etc.

1 Like

What do developers mostly use metatables for?

This would never compile.
​​​​​​​

The most common thing I’ve seen is using it for __index, but it generally depends on what you’re doing with your module. If you need custom functionality, then you’d want to use specific metamethods. __index is most used so that an custom object created by a module doesn’t need to have all of the methods assigned to it, it can just have it’s __index set, and then it can use all of the module’s functions.

Inheritance… that’s the shortest and most accurate answer anyone can give.

Oops! I do that all of the time. I went back and fixed it now.

1 Like

What is this suppose to do?

cdftvgybhunjmkjnhbgf

It doesn’t even return anything [the whole point of constructors] and I’m sure that wouldn’t even compile.

1 Like

That’s an incomplete constructor. I was just using it to show how setmetatable returns the table passed as the first argument. In a real constructor there would be more code below setting properties of self, or calling functions depending on what you are trying to do. As was mentioned by another commenter, it would end with return self.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.