小编典典

Ruby 是按引用传递还是按值传递?

all

@user.update_languages(params[:language][:language1],
params[:language][:language2],
params[:language][:language3])
lang_errors = @user.errors
logger.debug “--------------------LANG_ERRORS----------101-------------”
+ lang_errors.full_messages.inspect

if params[:user]
  @user.state = params[:user][:state]
  success = success & @user.save
end
logger.debug "--------------------LANG_ERRORS-------------102----------" 
                + lang_errors.full_messages.inspect

if lang_errors.full_messages.empty?

@userobject
将错误添加到方法中的lang_errors变量中update_lanugages。当我对对象执行保存时,@user我丢失了最初存储在lang_errors变量中的错误。

虽然我试图做的更像是一种黑客攻击(这似乎不起作用)。我想了解为什么变量值会被淘汰。我理解通过引用传递,所以我想知道如何将值保存在该变量中而不会被淘汰。


阅读 77

收藏
2022-05-10

共1个答案

小编典典

在传统术语中,Ruby是严格按值传递的。但这并不是您在这里真正要问的。

这个问题让人们感到困惑,因为有一个东西叫做引用类型,还有一个东西叫做 pass-by-reference,但它们实际上并没有太大的关系。

引用和值以及被引用的值:A(分类)简要概述

在按引用传递的情况下,函数的参数是对传递给函数的变量的引用,修改参数会修改原始变量。这不是Ruby。例如,让我们看下面的代码:

def inc(val)
  val += 1
end

a = 1
inc a
puts a

如果 Ruby 是一种按引用传递的语言,该程序将打印 2,因为val += 1ininc会增加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."替换值。如果 Ruby 不通过引用传递,这怎么可能?be_nice_to_me``"What? I didn't say anything."``change_string

好吧,还记得我之前谈到的那些引用类型吗?嗯,这就是 Ruby 中的对象。引用类型是其值是对其他事物的引用的类型。在这种情况下,变量的值是对字符串的引用"hello"。当您传递字符串时,变量的值(即引用)被复制到变量str中。所以现在它们都持有对同一个对象str的引用,但不是对be_nice_to_me. 因此,当您修改对象时,这些更改会显示出来,因为它们都指的是同一个对象。但是当您修改一个变量时,另一个变量看不到它,因为这两个变量都不是对另一个变量的引用

Ruby 是按引用传递还是按值传递?它是按值传递,但所有值都是引用。

Ruby
没有任何纯非引用值的概念,因此您当然不能将一个值传递给方法。变量总是对对象的引用。为了得到一个不会从你下面改变的对象,你需要复制或克隆你传递的对象,从而提供一个没有其他人引用的对象。(即使这也不是万无一失的,尽管
- 两种标准克隆方法都进行浅拷贝,所以克隆的实例变量仍然指向与原始对象相同的对象。如果 ivars
引用的对象发生变异,那仍然会出现在副本中,因为它引用了相同的对象。)

2022-05-10