What does table.__index = table do?

Hi, I was wondering what table.__index = table does (in reference to OOP and metatables).
I see people do it at the beginning at their scripts but I don’t know why. I’ve also searched up threads on it and they say that it allows you to do setmetatable(table,metatable) rather then setmetatable(table, [“__index”] = metatable) but what I’m wondering is why that happens and what is happening in the background. Thanks.

3 Likes

whenever a table does not have an index that is referenced with but it has a metatable with the __index metamethod lua will check if the table has the requested index, so this is useful when creating new instances:

local someClass = {}
someClass.__index = someClass

function someClass.new()
     return setmetatable({}, someClass)
end

function someClass:get()
     return 1
end

local something = someClass.new()

print(something:get())

At first lua will check if this table has the index with the function
but it does not, however it does a have a metatable with
the __index so it will check if this table has the index, so it
will call the Get() method, you can test this by removing
the line someClass.__index and you will get an error saying your attempting to
call a nil value.

5 Likes

Sorry but you didn’t really explain why it’ll call a nil if you remove someClass.__index = someClass. I understand that it won’t be able to access the get index but what I’m asking is why it wouldn’t be able too.

I said why, because when your creating a new instance what your basically doing is making a new table but setting its metatable to class, in this line:

return setmetatable({}, someClass)

so as you can see that table is just an empty table with no get method, and as I said earlier if you index a field which the table does not have lua will check if the metatable, which is someClass for the new instance, has the __index metamethod, and if it does lua will check if the table has the index and if it does will return the value, but if it does not have the metamethod then it will not check and only check the table itself.

5 Likes

I don’t think you are understanding what I’m asking, I’m asking about the line someClass.__index = someClass not where it sets the metatable for the new instance. What I’m asking is why your setting a tables metatable as it self and what __index has to do with it.

yes it is for the new instance, because you will be setting the metatable of the new instance to that table so it need to have the __index for the instance to access keys from someClass.

Ok I understand what your saying now but by setting the tables index to itself, when that instance needs to get the get function, what exactly is being done behind the scenes because wouldn’t that only put a empty __index metamethod into the someClass table that does nothing?

1 Like
someClass.__index = someClass
--is the same thing as
setmetatable(someClass, {__index = someClass})
2 Likes

what is going on behind the scenes is that the instance will check if someClass has index, if it references a index that it does not have.

1 Like

Oh, I understand now. Thanks a lot for your help, wouldn’t been able to figure it out without it.

2 Likes

Why would you do that, you’re basically just returning someClass when you call someClass.new(), or does it copy the table? I’m not really sure why you couldn’t just use someClass itself instead of someClass.new()

This gives you options for many cool things, in that example there is really no point, however, one of the main benefits of having a .new() method that creates and and returns the new metatable is that you can directly call a method off of the .new() function and it also gives you access to the self variable.

Could you provide an example of such a thing?

I’m on mobile rn so it’ll take a while. So instead I will link you 2 articles that helped me ALOT with metatables and metamethods, it is explained here:

As for metatables and metamethods, read this: