What is self and how can I use it?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I would like to make a character controller of @EgoMoose se

  2. What is the issue? Include screenshots / videos if possible!
    I don’t know what self is.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I don’t find a post that read about self.

I don’t want you to write a whole code, but a simple example would be good so I could understand it if I could. Thank you for reading until the end.

93 Likes

Assuming I have understood your post correctly, self is a Lua variable that is automatically assigned to when doing OOP related programming.

In Lua there are two ways to call a method.

someObject.Method()

and

someObject:Method()

These lines of code will both call the same method, however they’ll do something slightly different with the arguments.

local someObject = {
  Method = print
}

someObject.Method("Test") --> "Test"
someObject:Method("Test") --> table: 0x0000, "Test"

The reason you get table: 0x000 is because the object on which you call the method is passed as an argument automatically when using the : operator.

Now, where does the self variable fit into all of this? Well, you can also define a function using the same syntax as I have shown you above.

function someObject.Method(a, b)
  -- self does not exist here
end

and

function someObject:Method(a, b)
  -- self exists here
end

The difference is that the second example will also have the self variable defined and it’ll be set to the first value passed to the method.

For example

function someObject:Method()
  print(self)
end
someObject.Method("Test") --> "Test"

tl;dr the following two Lua snippets will do exactly the same thing.

function someObject.Method(self)
  print(self)
end

function someObject:Method()
  print(self) -- self is automatically defined
end
340 Likes

Thank for this interessanting Post :smile:

10 Likes

Complex has clearly already explained this well, but if you want my own explanation of it check out the first section of this tutorial:

25 Likes

Thanks @EgoMoose and @ComplexGeometry.

4 Likes

the self keyword has a realtionship with OOP Object Oriented Programming which you don’t really need to know to understand self but it is something you should really learn about!
The first part of this article made by Egomoose aswell explains a bit about OOP! link:link:
I also have an article that I made but it’s really just a mess and has a LOT of mistakes link:link: .

So, let’s start off, lua’s syntax allows you to turn tables into a some sort of object. We can put functions into tables.

local tab = {something = function(par) print(par) end} --"something" is the name of the function btw

--And if you wanna call that function that's stored inside of the table you would need to do
tab.something(2)

But lua’s syntax allows you to make functions inside of tables in another way!

local tab = {}

function tab.something(par) 
   print(par)
end
--this is littearly the same thing as above! but written out differently

tab.something(2) --calling it the same way

Now we’ll get back to this way of defining functions inside of tables later. If you think about it, there are two notations for functions, there are functions written out with a dot . and ones with the double dots : like methods. Something like part:Destroy() uses :, and there is something like math.floor() which uses ..

If we get back to the way we assigned the functions above. We can see we can actually do this as well, we can chose either a : function or a . function.

local tab = {}

function tab.something(par) 
   print(par)
end

tab.something(2)

--or this way!

function tab:something(par) 
   print(par)
end

tab:something(2) --very interesting isn't it?

Now, this is the exciting part, the part that has a relation with self.
Let’s say we have a table, that has a color property inside of it, (beacuse remember! tables kind of act like objects, like parts and other things, this has a relationship with oop). And this table would have a method, or in other words just a function that will change the color (a method is really just a function, but there are some minor differences). Let’s write that method in the 2 different ways above.

local object = {color = "blue"}
print(object.color) --prints blue, and you can see it kind of looks like an actual property, like part.BrickColor the one you're used to

function object.ChangeColor(object, color)
   object.Color = color
end

--You can see if we type it out this way! We have to specify the object
--That we wanna change its color in the paramaters.

function object:ChangeColor(color)
   self.Color = color
end

--You can see the usage of self pops up, and as well you can notice that we
--don't specify the table that we wanna change its color. Interesting!

Very interesting! Then what does self refer to? Well it refers to the object (table) that we are using the method on! The methods with the : notation kind of apply DIRECTLY on the object, while the ones with the . need the object affected to specified in the paramaters.

local object = {color = "blue"}
print(object.color) --prints blue, and you can see it kind of looks like an actual property, like part.BrickColor the one you're used to

function object.ChangeColor(obj, color)
   obj.Color = color
end

object.ChangeColor(object, "pink") --we have to specify the object!

function object:ChangeColor(color)
   self.Color = color
end

object:ChangeColor("pink") --In here self refers to "object"! It refers to the object that we are using the method on
86 Likes

Thanks you all very match :smiley:, all your Post are very Interessants.

4 Likes

@EgoMoose, why this?(i click on your Link)
I don’t understand why you write:

      local Placement.__index = Placement --???
3 Likes

That’s using metamethods, and in general metatables, which is indeed a big part of lua. I’d say there aren’t that many resources for learning about them, but I have writing something about them in my to-do list.

For now this video by ScriptGuider, a cool guy, should give a basic picture. But these are a big topic that again has a relation with OOP, search more about them!

9 Likes

@starmaq, thanks for send here this video, but why has @EgoMoose make a variable + Methametod:

local Placement.__index = Placement

The

Placement

is the Name of the Variable, but the

__index

Is a Methamethod. Can I union the two things (Placement + methamethod)?

local Placement = firstThing
local __index = Methamethod
local Union = Placement.__index --Its Possible???
2 Likes

You have some syntax errors in your post.

You should not be using the parentheses after function when defining a function like that. The parentheses are used after the name is given instead.

And here, the parameter should be an identifier (variable name), not a value. You meant to put color.

2 Likes

__index is a metamethod but when a metatable is not set, it is relegated to a table member. The case you’re seeing is declaring the member __index in the table Placement as itself. This is so that when setmetatable({}, Placement) is called, it uses Placement as the metatable. It’s functionally equivalent to setmetatable({}, {__index = Placement}).

The union you’re performing is possible but if you don’t set __index in Placement, it will be nil. Your variable is doing a table lookup and returning the value associated with that index. You cannot declare a member in a variable assignment if that’s what you were asking, but the raw code you wrote with no additions will work.

4 Likes

I just realised hehe really sorry
I was typing as fast as I can to get my answer posted first but I ended up losing the race anyways

I have really been making a lot of mistakes in my posts lately I gotta watch out

I’ll make sure to correct them

4 Likes

As colbert said, I think you kind of interpreted how that was written a bit wrong.
Placement is a table, and actually it’s a metatable because it has a metamethod in it. And basically what we’re doing is setting the table’s __index metamethod to itself.

5 Likes

Ok thx very much for say it me.

4 Likes

Hi, after 6 Months i now know OOP Programming, so i hope that i can explain it you:
Now we say you have a table (a table or a ModuleScript):

--I now will use ModuleScripts for example
ModuleScript = {}

return ModuleScript

Now we can create our function inside this table:

ModuleScript = {}

function ModuleScript.new(self)

end

return ModuleScript

We created a constructor with a doted function. Now, here self is not defined so we need to define we self:

ModuleScript = {}

function ModuleScript.new()
    local self = setmetatable({}, ModuleScript) --We now defined self
end

return ModuleScript

So, if we pass a parameter, the first parameter in the function will be the parameter of your choice. But in a DoubledDoted Function:

ModuleScript = {}

function ModuleScript:new(parameter)
    print(parameter) --Here, parameter is printed out, but self referes to the ModuleScript Table, so you dont need to insert in the parameters self or define it
end

return ModuleScript

So, if i now use my ModuleScript, you dont need to add self to the argumeters:

local Module = require(path) --The Reference of the ModuleScript

Module:new("Test") --Of the example above, this print Test out, and not the table, so you dont have to add the self to the argumeters

Hope you understand now.

Edit:

print() is a variadic function, so it accepts a unlimited number of parameters and argumeters. So, self is automatic printed out. Hope this will more help you:

--idk (i don‘t know) how the function `print()` exactly work, but this is more a little representation of my idea on how this should work:

function print(...) -- "..." represents a variadic function, you can pass a unlimited number of parameters, so a unlimited number of argumeters
    print(...) --This is not exatcly so, but as it accepts a unlimited number of parameters, self is so accepted and printed out.
end
5 Likes

print is not a method so there is no self here. Also, you should not use : for constructors since they are not methods. Also, a variadic function doesn’t necessarily mean “unlimited”. Since parameters are local variables you still need to comply with the 200-local-variable-limit.

1 Like

I tried to explain in a more “easy way”, but i know what you mean and you have right. print is not a method (a method is a function, or not? I not am programming lua since more as a week, so i forgot some things :sweat_smile:) and thaks for the thing with the variadic function.

3 Likes

Methods are functions, but the reverse isn’t necessarily always true. At least when talking OOP. A method is a member function.

4 Likes

Wow, i really need to go more in deep, i will search in google, thanks!
Edit: Here is a link if someone want to know more: programming practices - Method vs Function vs Procedure - Software Engineering Stack Exchange