Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
4

Use of Metatables? [closed]

Asked by
saenae 318 Moderation Voter
8 years ago

Hey, guys. I've been studying up on metatables for a little while, and I think I get the gist of how to use them. I also understand that they can be used for OOP, due to the events that they provide. I'm just wondering where this comes in use, since it seems as if you could do all of these things with a mix of regular functions and tables. Are they more efficient, or just make for cleaner code? Thanks a ton! :)

0
i don't want to type out an answer because i'm on mobile, but for one they are much more serviceable than a mixture of functions and tables. They are also quite a lot simpler to incorporate in lengthy code, because of their "metamethods". ImageLabel 1541 — 8y
0
Sorry to bother you like that, but thanks for the answer! I think I'm gonna run a few tests to see for myself exactly what I can do with it. Again, I appreciate the answer ^^. saenae 318 — 8y
0
Excellent question DigitalVeer 1473 — 8y

Locked by DigitalVeer, ISellCows, and Redbullusa

This question has been locked to preserve its current state and prevent spam and unwanted comments and answers.

Why was this question closed?

1 answer

Log in to vote
7
Answered by 8 years ago

Introduction

Let me give you an extremely rational summary of what a metatable is: A metatable defines the behavior for tables when dealing with special operations

Metatables are extremely powerful when dealing with tables and they basically control how the object will respond to different type of operations. Normally when one thinks of a table, he or she may see it as just a clean and organized way to merely store data such as variables, booleans, objects, and much more. However, the truth is that there are more to tables when you include metatables.

So what exactly are metatables and how can they be used?

To give a better understanding of how metatables and previously mentioned metamethods can come in handy, let me show you a small script.

With even a slight background knowledge with arrays, it should be pretty obvious that something is wrong here:

local ar1 = {1,2,3}
local ar2 = {3,2,1}

print(ar1 + ar2)

Upon the execution of the above code segment, Roblox spits back an error that looks like the following:

attempt to perform arithmetic on local 'ar1' (a table value)

Perhaps you are thinking, "But Veer, you can't add tables! That makes no sense! What on earth are you doing? Why are you even on this site?!"

The answer to your fits of outrage and confusion is actually the outstanding fact that we can indeed add these two tables! Thanks to the use of metatables and metamethods, we can detect whenever the addition operator is being used on a part and change the behavior of how the tables react accordingly!

Let's accomplish this task using metamethods. But first, we shall take a look at how the general construction for metatable looks like.

1.) Regular Array(s) Needed

local ar1 = {1,2,3}
local ar2 = {3,2,1}

Up above, we have our two arrays, ar1 and ar2, which we will be adding together. Now comes the next step which is creating the metatable.

2.) Create The Metatable / Metamethods

This part may seem a bit tricky, but try and follow along. Before I put the code, you need to understand that metamethods normally have two underlines before their name, and are the 'events' which we will connect. You can see the list of metamethods here and when they fire.

local meta = {
    __add = function(array,otherArray)
        local sum = 0;
        for i,num in pairs(array) do
            sum = sum + num;
        end
        for i,num in pairs(otherArray) do
            sum = sum + num
        end
        return sum;
    end 
}

Let me explain what this all is. First off, if you took a look at the link to the metatable wiki article, you would see that two values are returned by the _add metamethods. First understand that the add metamethod is called when the addition operator is used on a table. So now, all we are doing is telling the method what to do for the add metamethod. Second off, what is inside the scope of the add metamethod should be fairly straightfoward. We are iterating through the values of both arrays and merely adding it to sum, only to return it.

3.) Attach metatable

To attach a metatable to a table, there is a very specific command which must be used which is the setmetatable method. Now we just attach the metatables and allow the rest to do the work!

setmetatable(ar1,meta)
setmetatable(ar2,meta)
print(ar1 + ar2) -- 12

Tostring Metamethod

Incase the first example might have been a bit too complex, let me demonstrate another way to use metamethods. In this case study, we will take a look at the tostring metamethod which is called when the print or tostring method is used with the table as an argument.

Now, if you were to trying calling print on any ordinary array, you would most likely get a series of weird numbers. These weird numbers are actually called a 'Pointer' and they refer to the tables address in memory. However, when dealing with arrays, most likely you care about the content of the array rather than where its located in memory.

So lets create a simple array and try printing it:

local names = {"Digital", "Steve", "Bob"}
print(names)
--table: 151B50D0 [my output, yours will be different]

As you can tell, that looks nothing close to what printing a table should actually seem like. To get past this, we can modify the tostring metamethod to get something better to print!

local names = {"Digital", "Steve", "Bob"}
local meta = { __tostring = function(self) return table.concat(self, ", ") end }
setmetatable(names,meta)
print(names)

OUTPUT

Digital, Steve, Bob

As you can perhaps get closer to seeing, metamethods are extremely powerful with dealing with custom behavior for tables. But what about storing values? Metatables are extremely useful for protecting and hiding values which you perhaps don't want anyone to see for security reasons.

Index Metamethod

A common metamethod which is used is the__index metamethod which runs whenever you try to obtain something in a table that doesn't exist. For example, lets make a regular array with a couple of values, and see what happens when we try to index something that doesn't exist.

local coolScripters = {"DigitalVeer","saenae","BlueTaslem","Ezio Auditore"}
print(coolScripters[5])
--nil

Since we don't have a fifth element in the array, it only makes sense that we get nil as an answer. But what if we want something else to happen? What if we want a custom message to be returned for the output? Well, for this, we can use the __index metamethod!

local coolScripters = {"DigitalVeer","saenae","BlueTaslem","Ezio Auditore"}

local meta = { __index = function(self,index)
return "Sorry, but there is no value at \" coolScripters["..index.."] \"!"
end}

setmetatable(coolScripters,meta)
print(coolScripters[6])
--Sorry, but there is no value at " coolScripters[6] "!

Values In Metatables

Let's think of a scenario: You have a series of codes that if the user inputs, he or she will receive up to 3,000 in-game cash; However, you are worried about the user exploiting your script and changing the codes to whatever they want.

This is great because we can make values in a metatable read-only, which means that they can only be accessed but not changed.

First let's make our metatable and attach it to an array.

local ar = {}
local listOfCodes = {123235,3211,54645,231238}
setmetatable(ar,listOfCodes)

Now, there is another metamethod known as the __metatable metamethod which basically is called whenever one tries to access the metatable. We can use this to our advantage by basically redirecting the user to the original metatable incase they ever try to change it themselves. To do this, we have to just set the __metatable to return the original metatable each time.

setmetatable(ar, {__metatable = getmetatable(ar)}) 
print(getmetatable(ar))
--table: 19FF8800
setmetatable(ar,{})
--Error

Metatables are a pretty complex concept to grasp at first. However, after some practice along with trial and error, they will become a strong asset to you.

Useful Links

Metatables Lua PiL:http://www.lua.org/pil/13.html

Roblox Metatable Article:http://wiki.roblox.com/index.php?title=Metatable

Anaminus Summary:http://wiki.roblox.com/index.php?title=User:Anaminus/metatables_nutshell

Lua User Complex Tutorial:http://lua-users.org/wiki/MetamethodsTutorial

2
I definitely couldn't have asked for a more thorough answer. Thank you so much! saenae 318 — 8y
2
Just make this an article, hot damn NotSoNorm 777 — 8y
Ad