Все Переменные в Ruby - это ссылки на объекты. Вы не можете «передавать по значению» по сравнению с «передавать по ссылке» таким же образом, как у вас есть этот выбор на C, C++ или Perl. Фактически, Ruby силы проходят по значению, нет других вариантов. Однако отправляемые значения всегда являются ссылками на объекты. Это немного похоже на использование C или C++, где все переменные-члены являются указателями или используются Perl, где вы всегда должны работать со ссылками, даже при работе с простыми скалярами.
Я думаю, что это разделение переменной от данных объекта, которая вас сбивает с толку.
Несколько моментов:
Variable распределения никогда чрезмерно пишут другие переменные, которые могут указывать на тот же объект. Это в значительной степени определение pass-by-value. Однако это не соответствует вашим ожиданиям, что содержимое объектов также защищено.
Переменные и элементы в контейнерах (например, в Array
с и String
с) отдельные переменные, и если вы отправляете контейнер, может изменить его содержание непосредственно, потому что вы послали ссылку на контейнер, и который включает такие же переменные для его содержимого. Я думаю, что это то, что вы имеете в виду «как представляется, передача по ссылке»
Некоторых классов - в том числе тех представлений чисел, и Symbol
- неизменны, т.е. нет никаких изменений на месте методы для числа 4
. Но концептуально вы по-прежнему передаете ссылку на особый объект 4
в рутину (под капотом, для эффективности Ruby будет иметь значение 4
, закодированное просто в распределении памяти переменной, но это деталь реализации - это также значение " указатель "в этом случае).
Самый простой способ получить близко к «проходят по значению» семантикой вы, кажется, ищет с SampleModule
является clone
параметров в начале процедуры.Обратите внимание: это не приводит к тому, что Ruby изменяет семантику вызова, только в этом случае извне метода вы получаете безопасное предположение (независимо от того, что происходит с параметром внутри метода остается внутри метода), которое вам кажется нужным:
module SampleModule
def self.testing(o)
o = o.clone
o.test
end
end
- Технически это должно быть глубоко клоном, чтобы быть универсальными, но это не требуется, чтобы сделать ваш пример работу близко к пропуску по значению. Вы можете позвонить
SampleModule.testing(any_var_or_expression)
и знать, что все, что any_var_or_expression
находится в остальной части вашего кода, связанный с ним объект не будет изменен.
Возможно, вы можете уточнить, что 'o .clone' не _pass по значению_, но _ создает новый объект, копирующий переменные экземпляра клонированного объекта и возвращает it_; это означает, что переменные экземпляра нового объекта ссылаются на соответствующие переменные экземпляра клонированного объекта, что является решающим отличием от концепции «пройти по значению» – mdesantis
@ProgNOMmers - Да, я думаю, что я хотел использовать «глубокий клон», и мой пример работает только потому, что атрибут является числовым. С глубоким клоном вы становитесь ближе к поведению «pass by value» в принципе (так как во всем, что вы делаете с параметром внутри метода, не важно для вызывающего), хотя на самом деле, когда у вас есть глубокое дерево ссылок, это не такая чистая концепция в первую очередь. –
Это вещь, которую я пропускаю в Ruby: нет четкого способа сделать глубокий дубль объектов; в большинстве случаев вы должны реализовать его самостоятельно. – mdesantis