What does .__index do?

Hello I just wanted to know in oop why do some people do

module.__index = module

e.g.

local module = {}
module.__index = module

like what does it mean to do module.__index = module and why do people do it and how does it help?

5 Likes

It’s so that when you index for a nil value it falls back to the module table where all the methods are

1 Like

Can you give me an example of that?

2 Likes
local t = setmetatable({hello = nil},{
__index = function()
print("index fired.")
end;
})
print(t.hello) -- fires
2 Likes

i’ve mostly used __index for inheritance.


local Class = {}
Class.__index = Class

function Class.new(name)
    local object = {}
    object.Name = name
    setmetatable(object, Class)
    return object
end

function Class:GetName()
   return self.Name
end

return Class

now you can do this and the object created will have access to the modules :GetName function

local class = require(script.Parent)
local object = class.new("Dog")

print(object:GetName()) --> prints "Dog"

print(class:GetName()) --> prints "nil" 

this happens because the object didn’t have the function called :GetName() so it fellback on its index. (which is shared with the “Class” table/module) and found the function there instead.

so this is beneficial because you can share functions/properties instead of giving each object/table its own set.

someone correct me if im wrong though

14 Likes

Ok so I deleted my last post cause it was really confusing lol.

Alright:
local module = {LOL = 'hhaha"}

module.__index = module

Let’s define something thing’s here so I don’t make you confused

Module = the table called module above

CoolTable = A table which has it’s metatable attached to the table module using setmetatable

CoolTable also has some indexes, and values in it. CoolTable = {Hello = 'no'}

Based on the things I showed above it makes it so when CoolTable is indexed and the value of the index is nil, it fires .__index in Module. For example if we do CoolTable.LOL, CoolTable.LOL is nil so it fires.__index in Module. Now lua checks if the .__index is attached to a table. In this case yes, Module is attached to itself Module. Now lua returns the value of the index in Module.

In this case since Module.LOL is ‘hhaha’ it returns that.

so when we do print(Module.LOL) it print’s hhaha

Also keep in mind .__index can be attached to a function to, however I won’t be explaining that since your post asks about it attaching it to a table.












let’s explain some practical use cases of this. For example, two modules need the same set of functions and some additional functions. So why don’t we just make one module which contains these functions that these two modules will use so we don’t have to redefine the common functions in each module and waste memory?

local MasterModule = {}

MasterModule.__index = MasterModule

MasterModule.Echo = function(...)

print(...)

end

-----------------------------------------

local Module1 = {}

setmetatable(Module1, MasterModule)

Module1.Kill = function(Player)

if Player.Character then

Player.Character.Humanoid.Health = 0

end

end

-----------------------------

local Module2 ={}

setmetatable(Module2, MasterModule)

Module2.Kick = function(Player, Reason)

Player:Kick(Reason)

end

Module1.Echo("WOW I HAVE THE FUNCTION AND I DIDNT EVEN DEFINE IT IN MY MODULE XD")

Module2.Echo("OMG ME TO LOL ")

Both of them received Echo but all they had to do was set their metatable to the MasterTable. Instead of defining the Echo function in each module, we just make defined it in one table.

9 Likes

I see OOP examples, all you need is a diagram, so here you go, thrown together in about 5 minutes in paint because im bored
image

also didn’t include the fact that __index’s can be chained, but I felt that was out of the scope of this post, so quickly gonna bodge this for you

a = {c = 3}
b = setmetatable({b = 2}, {__index = a})
c = setmetatable({a = 1}, {__index = b})

print(c.a) --> 1 reading from itself
print(c.b) --> 2 reading from the __index table (which is b)
print(c.c) --> 3 reading from the __index table's __index (which is a)

__index is by far one of the most powerful metamethods out there, and it’s very useful in sandboxing. Roblox’s default ENV (holder of global variables) is actually a table with a locked metatable (out of this scope), that has an __index to the real ENV.

37 Likes