Наконец-то я нашел способ понять переменные и объекты, передачу по значению и передачу по ссылке. Это по-прежнему сложная тема, но я думаю, что есть способ проиллюстрировать концепцию с помощью IRB и некоторых общих объектов.

Начнем с двух строк

a = 'test'
b = 'test'
a.object_id != b.object_id

Когда две переменные содержат одну и ту же строку «значение», как в приведенном выше примере, оба объекта имеют разные идентификаторы объекта. Это означает, что это разные объекты. Таким образом, можно сказать, что строка "test" существует в памяти два раза.

a = :test
b = :test
a.object_id == b.object_id

С другой стороны, когда символ присваивается двум переменным, обе переменные указывают на один и тот же объект. Это означает, что символ :test существует в памяти только один раз. Независимо от того, где :test используется в программе, куда он передается или откуда на него делается ссылка, он всегда будет одним и тем же объектом.

a = true
b = true
a.object_id == b.object_id

Как насчет логического значения? И снова тот же объект. Логическое значение true (или false) существует в памяти только один раз, когда когда-либо переменной присваивается логическое значение, независимо от того, как это произошло, оно будет ссылаться на один и тот же объект в памяти.

Что меня поразило, так это объект nil. Когда переменной присваивается значение nil, она всегда будет указывать на один и тот же адрес в памяти.

a = nil
b = nil
a.object_id == b.object_id

Nil всегда имеет один и тот же идентификатор объекта

Я обнаружил, что идентификаторы объектов nil , true , false и целые числа всегда имеют одно и то же значение, независимо от системы.

nil.object_id  # 8
5.object_id    # 11
true.object_id # 20

Это показывает мне, что Ruby резервирует определенные идентификаторы объектов для этих объектов, потому что каждая переменная, назначенная одному из этих объектов, всегда будет указывать на один и тот же объект, хранящийся в памяти.

Неизменяемые объекты существуют только один раз в памяти

Моя упрощенная реализация заключалась в том, что когда объект в Ruby неизменяем, он также существует только один раз в памяти. Это означает, что все переменные, присвоенные этому объекту, всегда будут указывать на одно и то же адресное пространство.

a = 5
b = 5
a.object_id == b.object_id

Целые числа являются неизменяемыми объектами, поэтому переменные указывают на один и тот же объект.

a.to_s.object_id != b.to_s_object_id

Превращение объектов в строки переназначает переменные бота новому строковому объекту. Оба строковых объекта содержат значение "5", но являются разными объектами и находятся в разных местах памяти. Поэтому идентификаторы объектов разные.

Передача по значению и передача по ссылке

def shoveling(variable)
  variable << 33
end
number = 5
array = [5]
string = '5'
p shoveling(number) # 42949672960
p shoveling(array)  # [5, 33]
p shoveling(string)  # '5!'
p number # 5
p array  # [5, 33]
p string # '5!'

Это надуманный пример, но он показывает, что один и тот же метод name<< реализуется по-разному для разных классов объектов.

  1. В случае целого числа 5 передаваемый объект не изменяется, потому что целые числа неизменяемы, а Integer#<< не может изменяться.
  2. Массив с другой стороны видоизменен, и поэтому объект, на который указывает array, изменяется внутри и вне метода.
  3. То же самое касается объекта переменной string. Он мутирует как внутри, так и вне метода.

В чем преимущество передачи по значению или по ссылке?

Это не имеет значения! Для меня ruby ​​всегда передается по ссылке, потому что целое число 5 существует в памяти только один раз. Это означает, что переменная number и переменная variable будут указывать на один и тот же адрес в памяти при вызове метода.

Когда метод Integer#<< затем вызывается в следующей строке, объект не изменяется, а возвращается новый целочисленный объект, который возвращается методом.

Для меня большим прорывом стало осознание того, что все, что мне нужно сделать, это сначала посмотреть на объект и убедиться, что он неизменен.

И если объект изменчив, то посмотреть на методы и посмотреть, мутируют ли они переданные объекты.

Если объект неизменяем и если не используются методы мутации, нежелательных побочных эффектов быть не может!