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

Learning OOP and Metatables?

Asked by
Newrown 307 Moderation Voter
3 years ago

I plan on learning how to use metatables because I can see clear and obvious reasons how metatables can be very handy and useful when coding.

I was wondering where I should start, I have done some research, found some pretty decent and lengthy articles that can help.

However, if anyone can recommend where I could start learning in order to get the hang of metatables it would be much appreciated.

I am also thinking I am not the only one trying to learn how metatables work in order to advance their use of OOP, so I thought an answer to this question wouldn't just benefit me but everybody else with the same interest.

Any suggestions are appreciated. Thanks in advance!

0

2 answers

Log in to vote
2
Answered by
imKirda 4491 Moderation Voter Community Moderator
3 years ago
Edited 3 years ago

You can read this or this but metatables is what you need to know. I can give you simple explanation of how they work. First you need to know setmetatable function, it's a function that accepts 2 arguments, table and.. table where the first one is the one you want to set metatable to and the second one is the actual metatable. So you would do this

local MyTable = {}
local MyMetatable = {}

setmetatable(MyTable, MyMetatable)

--/getmetatable does what it says, it returns metatable which given table
--\is connected to, returns nil if none are
getmetatable(MyTable) -- returns MyMetatable

Now you have a metatable, but it's useless, that's why you use metamethods, the list of them is in the middle of this page, the most used metamethod is probably __index, here is how it works:

local MyTable = {}
local MyMetatable = {
    __index = print
}

setmetatable(MyTable, MyMetatable)

MyTable.NilValue('wideseal') -- prints wideseal

This will print because __index in this case refers to print, why? Because this is built in metamethod and it fires when you index table which MUST be connected to the metatable with the metamethod. __index is explained in roblox debhub like this: Fires when table[index] is indexed, if table[index] is nil. You see, if you index the table which is connected to metatable then your table will be connected to all the metamethods that the metatable it is connected to has so in our case it's only __index, this metamethod fires when indexed table key is nil, in our case i fired NilValue which is not a valid member of the table but since i indexed nil value, __index fired and in my case it returned print function as i set it to it. If you index non-nil value, nothing will happen:

local MyTable = {}
local MyMetatable = {}

function MyTable.test()
    print('check')
end

MyMetatable.__index = MyMetatable.test

setmetatable(MyTable, MyMetatable)

MyTable.test() -- prints check

MyTable.NilValue() -- prints check

Both of these print check, because test is not nil and we set __index to the test function, that way when you call a nil value, __index refers to MyMetatable.test so both the functions are the same. This is why you often see people doing:

MyMetatable.__index = MyMetatable

That way let's say you have some profile

local MyProfile = {
    Cash = 500,
}

You create a new function which will create you a new profile, let's call it new:

local ProfilerMaker = {}
ProfilerMaker.__index = ProfilerMaker

function ProfileMaker.new(Name)
    local NewProfile = {
        Cash = 500,
        Name = Name,
    }

    return setmetatable(NewProfile, ProfileMaker)
end

function ProfileMaker:Rob()
    self.Cash /= 2 -- divide by 2
    print(self.Name .. ' has been robbed!')
end

local MyProfile = ProfileMaker.new('kirda')

print(MyProfile.Name) -- kirda
print(MyProfile.Cash) -- 500

MyProfile:Rob() -- kirda has been robbed

print(MyProfile.Cash) -- 250

print(MyProfile.new == ProfileMaker.new) -- true

Now this may seem compicated but the last can help you understand it, in function new it created new table and set it's metatable to ProfileMaker, that way NewProfile table is connected to all metamethods of ProfileMaker which there is only one __index, NewProfile has it's own stats, Name and Cash which are the default values in this case. You see i printed MyProfile.Name and it returned kirda because it's apart of the table that new function returns but then i called :Rob() function which is NOT apart of the NewProfile BUT it's apart of the ProfileMaker and since there is __index and i indexed nil value, it will lead to the __index value which in this case is ProfileMaker so it will look for Rob function inside of the ProfileMaker which it exists. That way you can call all functions inside of ProfileMaker but what is self?

In OOP self is very important, i mean... no self no OOP, self = this in other languages if i am sure but no idea. self refers to the table itself and in the function Rob the self was MyProfile because i called it with : which puts self automatically, let's say those three methods are almost the same (except the last one):

workspace.Destroy(workspace) -- i used `.` so it does not have self, need to put it as the first argument
workspace:Destroy() -- normal
workspace.Destroy(Instance.new('Part')) -- i also did not use `.` but instead of workspace as self i put new part so this will destroy the newly created part by calling function of workspace

That might be confusing but if you would call MyProfile.Rob() then self would refer to the first argument you give you could do MyProfile.Rob(MyProfile) but you won't because that's the point of OOP, you can always not use OOP and get good results but OOP is just very comfortable to use.

Sorry the post got too long but here are sources you can read:

OOP1

OOP2

metamethods list

self

1
I haven't seen this much dedication in a while, though is expected for a rudimentary introduction to metatables. Keep up the good work! Ziffixture 6913 — 3y
0
thanks for the good words and thanks also for this: it showed me notification about your comment and i found big mistake in all my examples, i called MyMetatable.Func instead of MyTable.func imKirda 4491 — 3y
0
Thank you! I still don't have a fully clear understanding of it, however this cleared up a lot for me, I am going to look into the articles in order to have a better understanding of this. I understand that this clearly took you a long time to write but you really helped a lot, this was much appreciated! Thank you again. Newrown 307 — 3y
Ad
Log in to vote
1
Answered by 3 years ago
Edited 3 years ago

The only reason I learned how a metatable worked was through this simple but very teaching variable I found on another script.

This may seem like nothing but it really gets you far into it, I suggest taking some time and looking through other threads through the Developer Forum to get a better grasp on it. Otherwise, the best starting place would be learning about Metatable.__index and Metatable.__newindex most importantly, they are what make up most of the scripting you see.

This will eventually help you learn the other metamethods and it has helped me a lot.

local S = setmetatable({}, {__index = function(self, index) return game:GetService(index) end})

local Players = S.Chat -- aka game:GetService("Players")

I can guess why you find them very useful, they are. I hope you take this answer and find the time to research them, they aren't as bad as they seem.

These will confuse you, as they did to me. There's not really any good tutorial but I could suggest some YouTube tutorials for Lua metatables, the roblox metatable tutorials don't really go in depth from what I've discovered.

0
Thank you for the answer, much appreciated, will look into it Newrown 307 — 3y

Answer this question