Metamethods are special functions that allow you to override specific operations performed on Lua tables. When a table of metamethods is applied to a table, it is then known as its Meta Tables. When used correctly, they can allow tables to behave in very unique and complex ways that would not otherwise be possible. They are also the powerhouse behind object oriented programming in lua.
You can live a fulfilling life in Lua without metatables, but hopefully with a practical example you will see their usefulness.
Shown here is how some metamethods of a metatable fit together.
Perhaps the most useful of the metamethods are the __call and __index entries.
__call allows tables that have a metatable to be called like a function, with the table being passed as the first argument.
__index is far more interesting and is what gives metamethods most of their power. It can either be a table, or a function.
If it's a table, the object will lookup entries in it for the specified key. This is what allows functions defined in the meta.__index table to be called on the object table. Refer to the "metaIndex" variable written in the first example.
If this index table also has its own metatable and does not find the key, then this new metatable will be used and it will follow the chain up until it reaches a return value or the end of the index chain, whichever comes first. Here is an example of what this looks like.
Used correctly this will achieve outcomes very similar to how entity .Base inheritence works.
And if it's a function, it will call the function and provide the returned value. This example is the simplest way to give a table a "default value".
It's possible to write metatables much smaller than what is shown here, and with less complexity by setting the metatable __index entry to reference the metatable. Example:
There are many different ways to write metatables, and it all comes down to what you'll be using it for and what you need Lua objects to do.
All metamethod names begin with __, and are named logically (e.g. __add corresponds to the + operator).
see this page for more thorough descriptions of each metamethod.
One common programming task is to compare one item against many. For instance, when we want to check whether a player has said a keyword, you could use table.HasValue
The issue with this approach is that HasValue is essentially a for loop checking if the fruit variable is equal to the word variable. With large tables, if you check HasValue frequently enough it will really slow down your program! Instead, we can make this more efficient by doing the following.
This solution is pretty elegant. hasFruit[...] will return true if the word is in our table, and nil otherwise.
An example that puts multiple metamethods to use is this Set script, which shows the possibilities of what you could do with metamethods. You can easily run the following code by creating a custom .lua script in the lua/autorun folder. Happy learning!
All of the fruits are printed out as expected, though keep in mind that this is an unordered set of elements. If you want them in a specific order,you will have to sort them.