What is the self keyword in Lua?

Im very familiar with module scripts but i have no idea what self is or meta tables or oop in general

Can anyone explain any of these?

1 Like
local Table = {
  SomeValue = 1;
  Func = function(self)  -- self would be the table that this function is in, which is "Table"
      print(self.SomeValue) -- If called with :, self is automatically passed and it will print "1"
  end 
}

Table:Func() -- prints 1
Table.Func() -- won't work because calling the function with . doesn't automatically pass self

-- You can also do this:
Table.Something = 2
function Table:DoSomething() -- If you use : like this, it will automatically pass self and you don't have to add it as a paramter
   print(self.Something) -- 2
end

Table:DoSomething() -- prints 2

Essentially, self just refers to the table that the function is in. Self is automatically passed when you use the colon when defining and calling the function.

3 Likes

What would this help with while coding?

1 Like

It’s really just a shorthand. Not technically needed, but saves some typing and helps make sure you are only passing in the table you think you are.

2 Likes

It’s mostly used for OOP classes. Constructing functions inside tables with the : operator are called methods (which are functions “attached” to some class).

Methods are just syntactic sugar for the . operator. As stated above, using the : operator will automatically pass itself, hense the self. You can fire them both ways:

module:method()
module.method(module)

The big benefit to using the : operator is that intellisense will not pick up on functions when typing with a . operator.

Examples:

function module.method(self: typeof(module))
    -- intellisense will also show method when using the dot operator
    -- and the colon operator, **assuming** you strictly define self
end

function module:method()
    -- however, intellisense will only show this using the colon operator,
    -- which is a good way to ensure you are not accidentally using
    -- the dot operator without passing in itself
end
2 Likes

self is a keyword generally used in OOP to refer to the current object you are editing. In Luau, it is also used to refer to a table the specified function is in, like @SeasonedRiceFarmer said.

sorry to the person above me about calling methods in different ways I actually typed this out before you replied and didn’t want to get rid of it

There’s two ways of calling a method:

  • Dot Notation
  • Colon Notation
local tbl: {({any}) -> ()} = {}

function tbl:funcOne()
    print(self)
end

tbl.funcOne() --> this would output nil as self has not been defined

--these two have the same effect
tbl.funcOne(tbl)
tbl:FuncOne()

This is crucial in OOP so each object actually knows what object to reference (it needs to reference itself).

local Class = {}
Class.__index = Class


function Class:OutputClass()
    print(self.PlayerName)
end

function Class.new(playerName: string)
    local self = setmetatable({}, Class)
    self.PlayerName = playerName

    return self
end

return Class

Now, if we required this module, and ran this code:

local Class = require(path_to_module)

local obj1 = Class.new("bob")
local obj2 = Class.new("emily")

obj1:OutputClass() --> outputs "bob"
obj2:OutputClass() --> outputs "emily"




You also mentioned metatables.
I think the best way to think about a metatable is “a table about a table”. It holds information about the table and how it should behave.

This metatable can also include metamethods. These change how certain actions are performed on the table.

For example, the __index metamethod is invoked when an index in a table is not found (it is nil). You can redirect Luau to another table, where the desired method should hopefully be.

local tbl: {any} = {
    ["keyOne"] = "valueOne",
    ["keyTwo"] = "valueTwo"
}

setmetatable(tbl, {
    ["__index"] = function(self, index)
        warn("Index was not found in table")
        
        return 3 --this will cause any nil indexes to return 3
    end
})

--so, if we did this:
local value = tbl.keyThree

--tbl.keyThree is nil, so Luau is redirected to that function and 3 is returned
print(value) --> outputs 3






This is incredibly helpful for inheritance in OOP.

--create a class
local Class = {}

--set up this metamethod for future inheritance
Class.__index = Class

--methods for the class
function Class.method1()
    print("Luau was redirected to this subprogram.")
end

--class constructor
function Class.new()
    local self = setmetatable({}, Class) --note self has inherited __index and it is set to the class

    --assign items specific to this object
    self.Item1 = 3
    self.Item2 = 4

    --try and call the method
    self:method1()

    --this method was nil, so __index was invoked
    --the method was found in Class, so it was run there with the provided parameters. which in this case, was the object itself
end

return Class

Please let me know if you need me to explain this further, I don’t know how well I explained it here especially because I had to compress a lot of information.

2 Likes

I understood this pretty well, i will keep re reading this today. Can you explain a little about what oop excatly is and its purpose?

OOP (Object-Oriented Programming) is a programming paradigm based around user-defined classes. It helps to keep code neat and readable, as well as keeping it simple and efficient. It’s typically used for things you need a general framework for, which require seperate methods, for example enemies in a tower defense simulator. Be aware an Object-Oriented structure will be more impactful on memory.

You must create a class, and then use a class constructor to create an object of that class, typically named Class.new. Luau does not support full OOP, it instead uses metatables to create “mock-OOP”, but it produces an almost identical result.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.