I am currently learning OOP and I’d like to ask what the Self keyword means, what it’s used for and why I’ve searched for definitions of it but it’s very confusing.
self
is widely recognised across many programming languages in OOP. It’s used to refer to the current object you are editing. For example, when creating an object through a class constructor, you would likely use self
to store the object.
local self = setmetatable({}, Class)
It’s just like naming conventions (is a naming convention?) and indicates to others reading the code that it’s an object. When using colon notation, self
is automatically defined as the first parameter.
local Class = {}
Class.__index = Class
function Class:SomeMethod()
print(self) --outputs all items of the class as they were created in Class.new
end
function Class.new(): ClassType
local self = setmetatable({}, Class)
self:SomeMethod() -- same as doing self.SomeMethod(self)
return self
end
export type ClassType = {
["new"]: () -> (ClassType),
["SomeMethod"]: (self: ClassType), -> (nil)
--regardless whether we did self:ClassType there, self would still be defined.
}
return Class
Here’s some more information from a post which has a similar question?
If you have any more questions, please ask! I don’t know how well I’ve explained it here.
So say I created an Class called Enemy’s and one of them was a Zombie. When I use a function for the zombie to damage the player and I’m getting the zombies damage amount I would not use Zombie.Damage I would use Self.Damage?
Yes, if you wanted to change the damage of that one individual zombie you would use the parameter holding the zombie object and not the class name.
function Class:SomeMethod()
end
When creating the functions we use the class name to define it. This is because setmetatable
in the class constructor will cause the object to inherit everything from the class, including these methods.
Like i said above if you want to change an item within an object use the variable that represents it and not the class name. Using the class name would change that thing for all future objects.
Sorry but I dont really understand what your saying in the 2nd and 3rd paragraph
self
is just a variable that points to a method’s table.
local t = { k = 1 }
function t:print()
print(self.k) -- 'self' points back to 't'
end
It’s not tied to OOP specifically; OOP just uses it a lot.
You use it because with OOP, you create multiple objects that behave differently from each other.
If you just used t
on it’s own, you will be pointing back to the original table every time. In OOP, you create a unique table that behaves on it’s own without being tied to the original one, and self
is how you access the unique table.
local t = {}
t.__index = t
function t.new()
return setmetatable({k=2}, t) --> create a new object
end
function t:print()
print(self.k) --> prints '1' because the newly created object has it
print(t.k) --> 'k' doesn't exist in the original 't' table, so this will print nil
end
-- Usage
local j = t.new() --> make the new object
j:print() --> call the method on the new object
-- Likewise, if you did
t:print()
-- this will print 'nil' twice
TL;DR: self
is basically a variable name that gets a special syntax highlight because it should only be used for OOB.
I Like Reading:
self
is a variable that is typically returned at the very end of a SomeClass.new(args)
function. Let’s say we made a car factory with this module script.
--somewhere in a module script...
local Car= {}
Car.__index = Car
function Car.new(numPassengers, type, color)
local self = setmetatable({}, Car)
self.passengers = numPassengers
self.type = type
self.color = color
return self
end
return Car
Alright, let’s go over this piece of code.
Imagine that this is your car factory. It contains the instructions on how to make a car. Customers (scripts) can ask the car factory “hey I want a car that can hold 7 people, is a van, and is lime green”.
local myNewCar = Car.new(7, "van", rgb(0,255,0))
The car factory says “ok, here’s your car”.
return self
The customer (your script) and the car factory (the module script) call the car by a different name.
YOU call it myNewCar
and the FACTORY calls it self
. In fact it individually calls all the cars it has ever made self
.
If this were real life you would call your car “My Car”; It belongs to you.
The car factory sees it as the customer’s car, whoever the customer happens to be is not important to the factory. The car factory sees many different customers every single day and doesn’t have enough time to care.
So:
YOU call it
myNewCar
the factory calls it self
Still with me? Cool.
Now you might want to drive your car.
myNewCar:Drive
Your car has a method (a function) for that, called Drive
.
--somewhere in the same module script as before
function Car:Drive(speed)
--driving code
end
All of these methods are sent back when we return the Car
module, and can be accessed by you, the customer/driver. When YOU (the customer/driver) call one of these methods, it executes only on YOUR car.
You might not be understanding what the __index metamethod does in a metatable.
local Class = {}
Class.Property = "Class"
function Class:DoAThing()
print(self.Property)
end
Class:DoAThing() --> Class
local instance = {}
instance.Property = "Instance of Class"
setmetatable(instance, { __index = Class })
instance:DoAThing() --> Instance of Class
When indexing a field in a table (a colon is just a special way to index a function). If it doesn’t exist and the table’s metatable has a __index field defined, it will check that table as well. This is how instance
finds the DoAThing
method above.
Because self
refers to the table the method was called on, when I call Class:DoAThing(), it will index the Class table. When I call it on instance, it will index the instance table.
To add on to this,
instance:DoAThing()
--is the same as
instance.DoAThing(instance)
-- where
function Class:DoAThing()
-- is the same as
function Class.DoAThing(self)
not metaphorically, these are the exact same in lua. A colon is just passing the table as its first parameter and naming it self.
Calling a : method with a . will rename the first parameter to self without explicitly declaring it.
function Class:DoAThing()
print(self.Property)
end
instance.DoAThing( {Property = "Hi!" } ) --> Hi!
I already know all about metatables and metamethodes especially what __index does dw.
So Self basically represents the Table your using that function on?
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.