考虑到在Ruby编程语言中,所有的东西都被认为是一个对象,我认为将参数传递给方法是通过引用来完成的。然而,下面这个小小的例子让我感到困惑:
$string = "String"
def changer(s)
s = 1
end
changer($string)
puts $string.class
String
=> nil正如您所看到的,原始对象没有被修改,我想知道为什么是,以及我如何才能完成期望的行为,即。获取方法来实际更改其参数所引用的对象.
发布于 2011-10-07 14:22:26
Ruby的工作方式是按值传递和通过引用传递的组合。实际上,Ruby在引用中使用pass值。
您可以在以下线程中阅读更多内容:
一些值得注意的引语是:
绝对正确: Ruby带有引用。
:004:0> def foo(x) x= 10 => nil irb(main):005:0> def bar;x= 20;foo(x);x end => nil irb(main):006:0> bar => 20 irb(main):007:0>
在调用作用域中,没有任何标准的方法(例如,除了涉及eval和元编程魔术)使变量指向另一个对象。而且,顺便说一句,这与变量引用的对象无关。Ruby中的直接对象与其他对象无缝集成(例如,与Java中的POD不同),从Ruby语言的角度来看,您不会看到任何不同(除了性能之外)。这就是为什么Ruby如此优雅的原因之一。
和
向方法传递参数时,传递指向引用的变量。在某种程度上,它是由值传递和引用传递的组合。我的意思是,将变量的值传递给方法,但是变量的值始终是对对象的引用。
以下两者之间的区别:
my_method( A) a.gsub!( /foo/,'ruby‘)结束str = 'foo是可怕的’my_method( str ) #=> 'ruby是可怕的‘str #=> 'ruby是可怕的’
以及:
def your_method( A)a= a.gsub( /foo/,'ruby‘)结束str = 'foo是可怕的’my_method( str ) #=> 'ruby‘str #=> 'foo是可怕的’
在#my_method中,您正在调用#gsub!它改变了已到位的对象(a)。因为'str‘变量(在方法范围之外)和'a’变量(在方法范围内)都有一个“值”,即对同一个对象的引用,因此在调用方法之后,对该对象的更改将反映在'str‘变量中。在#your_method中,调用#gsub不修改原始对象。相反,它创建一个包含修改的字符串的新实例。当您将该对象赋值给“a”变量时,您将“a”的值更改为对该新字符串实例的引用。但是,'str‘的值仍然包含对原始(未修改的)字符串对象的引用。
方法是否更改引用或引用对象取决于类类型和方法实现。
string = "hello"
def changer(str)
str = "hi"
end
changer(string)
puts string
# => "hello"string不会更改,因为字符串上的赋值替换引用,而不是引用值。如果你想修改字符串的位置,你需要使用String#replace。
string = "hello"
def changer(str)
str.replace "hi"
end
changer(string)
puts string
# => "hi"String是一种常见的情况,大多数操作都在克隆上工作,而不是在self实例上工作。出于这个原因,有几个方法有一个执行相同操作的bang版本。
str1 = "hello"
str2 = "hello"
str1.gsub("h", "H")
str2.gsub!("h", "H")
puts str1
# => "hello"
puts str2
# => "Hello"最后,要回答原来的问题,您不能更改字符串。您只能给它分配一个新值,或者将字符串包装到一个不同的可变对象中,并替换内部引用。
$wrapper = Struct.new(:string).new
$wrapper.string = "String"
def changer(w)
w.string = 1
end
changer($wrapper)
puts $wrapper.string
# => 1发布于 2011-10-07 14:23:44
赋值不将值绑定到对象,而是将对象引用绑定到标识符。参数传递的工作方式也是一样的。
当您输入函数的主体时,世界如下所示:
+---+ +----------+
| s |----------------->| "String" |
+---+ +----------+
^
+-------+ |
|$string|--------------------+
+-------+密码
s = 1让世界看起来像
+---+ +---+ +----------+
| s |------>| 1 | | "String" |
+---+ +---+ +----------+
^
+-------+ |
|$string|--------------------+
+-------+赋值语法操纵变量,而不是对象。
与许多类似的语言(Java、C#、Python)一样,ruby是按值传递的,其中的值通常是引用的。
若要操作string对象,可以在字符串上使用方法,例如s.upcase!。这类事情将反映在方法之外,因为它操作对象本身。
发布于 2011-10-07 14:16:57
因为$string和s都是对同一个对象的引用,所以字符串" string“。但是,当您将s分配给1时,您不会更改对象"String",而是让它引用一个新对象。
https://stackoverflow.com/questions/7688391
复制相似问题