Object Oriented Programing introduce a new keyword self
. This keyword is used in different context.
Calling Methods with self
A classic error made when learning to use classes and instance methods is to assign new value to a newly initialized local variable instead of the setter method.
class Obake
def initialize(name, age)
@name = name
@age = age
end
def change_info(name, age)
name = name
age = age
end
private
attr_accessor :name, :age
end
We know we need setter methods (provided by attr_accessor
) to modify the @name
and @age
instance variables. However, in the change_info
method we are not calling those two setter methods. Instead, we are initializing new local variable name
and age
. As thoses are scoped to the method scope (see also Local Variable Scope), they cease to exist when the method returns.
What we really want to do is reassign the instance variables using setter methods. This can be done thanks to self
to let Ruby know we’re calling a method:
class Obake
def initialize(name, age)
@name = name
@age = age
end
def change_info(name, age)
self.name = name
self.age = age
end
private
attr_accessor :name, :age
end
It is possible, though not required, to use self
on getter methods as well. Rubocop will probably flag it:
C: Style/RedundantSelf: Redundant self detected. (https://github.com/bbatsov/ruby-style-guide#no-self-unless-required)
"My name is #{self.name} and I am #{self.age}!"
^^^^^^^^^
C: Style/RedundantSelf: Redundant self detected. (https://github.com/bbatsov/ruby-style-guide#no-self-unless-required)
"My name is #{self.name} and I am #{self.age}!"
^^^^^^^^
Last but not least, we can use self
on any instance method, not just accessor methods.
Method Definitions with self
self
is used to define class methods. See Instance Methods vs. Class Methods.
Using self
inside a class but outside an instance method refers to the class itself.
class Obake
puts "I am a good #{self}."
end
Obake # => I am a good Obake.
From the example above, we can see how a method defined using self
is a class method: def self.my_method
is the same as def Obake.my_method
.
Referencing the Calling Object
Imagine a method what_is_self
that returns self
:
class Obake
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def what_is_self
self
end
end
tommy = Obake.new('Tommy', 204)
arthur = Obake.new('Arthur', 340)
p tommy.what_is_self # => #<Obake:0x000055f7cf7da3a8 @name="Tommy", @age=204>
p arthur.what_is_self # => #<Obake:0x000055f7cf7da330 @name="Arthur", @age=340>
We can see that from within the class, when an instance method uses self
it reference the calling object. In this case it’s the tommy
and arthur
objects.
This means calling self.name=
(name=
being the setter method) inside an instance method acts the same as calling tommy.name=
from outside the class.