Ruby - параметры по ссылке или по значению?
Я не понимаю, почему они говорят, что Ruby передает все параметры по значению, и в то же время следующий код доказывает обратное:
class MyClass1
@var1 = 123
def get1
@var1
end
def set1=value
@var1 = value
end
end
c1 = MyClass1.new
c1.set1 = 444
p c1.get1 # 444
def test1 mc
mc.set1 = 999
end
test1 c1
p c1.get1 # 999
Если бы это было по значению, это распечатало бы 444
не 999
,
1 ответ
Этот вопрос сбивает с толку людей, потому что есть вещь, называемая ссылочным типом, и есть вещь, называемая передачей по ссылке, но на самом деле они не имеют ничего общего друг с другом.
Ссылки и значения и значения, которые являются ссылками: краткий обзор A (sorta)
В сценарии передачи по ссылке параметры функции являются ссылками на переменные, которые были переданы в функцию, а изменение параметров изменяет исходные переменные. Это не то, что Руби. Например, давайте посмотрим на следующий код:
def inc(val)
val += 1
end
a = 1
inc a
puts a
Если бы Ruby был языком передачи по ссылке, эта программа напечатала бы 2, потому что val += 1
в inc
будет увеличивать значение a
, Но это не то, что происходит. Переменная val
не является ссылкой на переменную a
- это независимая переменная, которой присваивается то же значение.
"Но ждать!" ты говоришь. "Что если мы имеем дело с объектами? Конечно, переменные объекта передаются по ссылке, верно?"
Нету.
def change_string(str)
str << " I can insult you all you want"
str << " because you'll never see this"
str << " because I'm going to replace the whole string!"
str << " Haha you smell bad!"
str = "What? I didn't say anything." # I'm so sneaky
end
be_nice_to_me = "hello"
change_string(be_nice_to_me)
puts be_nice_to_me
Если бы Ruby передавался по ссылке, вы бы никогда не увидели, как change_string
метод, потому что str = "What, I didn't say anything."
полностью заменит значение be_nice_to_me
со строкой "What? I didn't say anything."
Но по факту change_string
Грехи обнажены на всеобщее обозрение. Как это возможно, если Ruby не передается по ссылке?
Ну, помните те ссылочные типы, о которых я говорил ранее? Ну, это то, что объекты в Ruby. Ссылочный тип - это тип, значение которого является ссылкой на что-то другое. В этом случае значение переменной является ссылкой на строку "hello"
, Когда вы передаете строку, значение переменной, которая является ссылкой, копируется в переменную str
, Так что теперь они оба содержат ссылки на один и тот же объект, но str
не является ссылкой на be_nice_to_me
, Поэтому, когда вы изменяете объект, эти изменения появляются, потому что они оба ссылаются на один и тот же объект. Но когда вы изменяете одну переменную, другая не видит ее, потому что ни одна переменная не является ссылкой на другую.
Так является ли Ruby передачей по ссылке или передачей по значению? Это передача по значению, но все значения являются ссылками.