As you learn your way through Ruby’s OOP, you will eventually stumble upon the concept of object passing. It might not be very clear if Ruby uses pass-by-reference or pass-by-value to send objects to a method. So I’m going to explain how all that works.
What is pass-by-reference?
Pass-by-reference means that the arguments of a method are references to the variables that were passed into the method, and modifying the arguments modifies the original variables.
val = "Hello"
def my_method(arg)
arg = "Hi"
end
my_method(val)
puts val # => In pass-by-reference the result would be "Hi"
If Ruby were pass-by-reference, changing the value of the argument (arg)
would change the value of the variable val
. That is because in pass-by-reference, arg
is a reference, a memory address. It’s not the actual string "Hello"
.
What is pass-by-value?
On the other hand, pass-by-value means that the arguments of a method are the values of the variables that were passed into the method, and modifying the arguments does not modify the original variables.
val = "Hello"
def my_method(arg)
arg = "Hi"
end
my_method(val)
puts val # => In pass-by-value the result would be "Hello"
What is a reference type?
There’s one more concept you need to understand before I can answer the main question. And that is about reference types.
A reference type is a type whose value is a reference to something else. Let me explain.
So when you pass the variable some_string
to a method, the method receives a copy of some_string
‘s value, which is a reference.
As you can see in the image, what is passed into my_method
is not a reference to some_string
. It’s the value of some_string
. But that value is actually a reference to the Hey There!
object.
That means that if you were to modify arg
, the changes would be seen by some_string
, because they are both refering the same object in memory.
Example:
some_string = "Hey There!"
def my_mehtod(arg)
# Changing the value of `arg`
arg = "Hello!"
end
my_mehtod(some_string)
puts "The value of some_string is: #{some_string}"
# => The value of some_string is: Hey There!
Now, let’s change the behavior of my_method
to modify the object that it references.
some_string = "Hey There!"
def my_mehtod(arg)
# Changing the value of the object it references
arg.gsub!(/Hey/, "Hi")
end
my_mehtod(some_string)
puts "The value of some_string is: #{some_string}"
# => The value of some_string is: Hi There!
See what happened there? By changing the actual string that arg was refering to, made it visible to some_string
because we changed the object that both arg
and some_string
refer to.
So is Ruby pass-by-reference or pass-by-value?
As you can see from the examples above, what is actually passed into the method is the value. But that value is actually a reference. So even though the terminology is confusing, I would say Ruby is pass-by-value, but all the values are references.