如果在 Ruby 中一切都是对象,为什么这不起作用?
考虑到在 Ruby 编程语言中,一切都被称为对象,我可以放心地假设将参数传递给方法是通过引用完成的。然而下面的这个小例子让我困惑:
$string = "String"
def changer(s)
s = 1
end
changer($string)
puts $string.class
String
=> nil
正如你所看到的原始对象没有被修改,我想知道为什么,而且,我怎样才能完成所需的行为,即。 获取实际更改其参数引用的对象的方法。
Considering that in the Ruby programming language everything is said to be an Object, I safely assumed that passing arguments to methods are done by reference. However this little example below puzzles me:
$string = "String"
def changer(s)
s = 1
end
changer($string)
puts $string.class
String
=> nil
As you can see the original Object wasn't modified, I wish to know why, and also, how could I accomplish the desired behavior ie. Getting the method to actually change the object referenced by its argument.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Ruby 的工作方式是按值传递和按引用传递的组合。事实上,Ruby 使用带引用的值传递。
您可以在以下主题中阅读更多内容:
一些值得注意的引用:
和
方法是否更改引用或引用的对象取决于类类型和方法实现。
string
未更改,因为字符串上的赋值替换了引用,而不是引用的值。如果你想就地修改字符串,你需要使用
String#replace
。字符串是一种常见情况,其中大部分操作都在克隆上进行,而不是在自身实例上进行。
因此,有几种方法都有一个 bang 版本,可以就地执行相同的操作。
最后,为了回答您原来的问题,您不能更改字符串。您只能为其分配新值或将字符串包装到不同的可变对象中并替换内部引用。
The way Ruby works is a combination of pass by value and pass by reference. In fact, Ruby uses pass by value with references.
You can read more in the following threads:
Some notable quotes:
and
Whether a method changes the reference or the referenced object depends on the class type and method implementation.
string
is not changed because the assignment on strings replaces the reference, not the referenced value.I you want to modify the string in place, you need to use
String#replace
.String is a common case where the most part of operations works on clones, not on the self instance.
For this reason, several methods have a bang version that executes the same operation in place.
Finally, to answer your original question, you cannot change a String. You can only assign a new value to it or wrap the string into a different mutable object and replace the internal reference.
赋值并不将值绑定到对象,而是将对象引用绑定到标识符。参数传递的工作方式相同。
当您进入函数体时,世界看起来像这样:
代码
使世界看起来像
赋值语法操作的是变量,而不是对象。
与许多类似的语言(Java、C#、Python)一样,ruby 是按值传递的,其中值通常是引用。
要操作字符串对象,您可以使用字符串上的方法,例如
s.upcase!
。当方法操作对象本身时,这种事情将反映在方法之外。Assignment does not bind values to objects, it binds object references to identifiers. Argument passing works the same way.
When you enter the body of the function, the world looks like this:
The code
makes the world look like
The assignment syntax manipulates variables, not objects.
Like many similar languages (Java, C#, Python) ruby is pass-by-value, where the values are most often references.
To manipulate the string object, you can use a method on the string, such as
s.upcase!
. This sort of thing will be reflected outside of the method as it manipulate the object itself.因为
$string
和s
都是对同一个对象(字符串“String”)的引用。但是,当您将s
分配给1
时,您不会更改对象“String”,而是使其引用一个新对象。Because both
$string
ands
are references to the same object, the string "String". However, when you assigns
to1
, you don't change the object "String", you make it reference a new object.Ruby 将值传递给函数,这些值是对对象的引用。在您的函数中,您将
s
重新分配给另一个值,在本例中是对1
的引用。它不会修改原始对象。您的方法不会更改传入的对象,您正在更改
s
引用的内容。Ruby passes values around to functions, and these values are references to objects. In your function you are reassigning
s
to another value, in this case a reference to1
. It does not modify the original object.Your method isn't changing the object passed in, you're changing what
s
refers to.实际上,大多数托管编程语言,如 java 、 c#...几乎都不是按引用传递...
它们都按值传递引用...这意味着它们创建另一个指向同一对象的引用...分配它具有新值不会更改原始引用的值...只是 s 指向的内容...
此外,字符串在大多数语言中都是不可变的,这意味着您无法在创建后更改该值..它们必须是重新创建为新的......所以你永远不会看到实际字符串有任何变化......
Actually, most managed programming languages like java , c#... almsot all do not pass by reference...
They all pass the reference by value ... that means they make another reference that point to the same object ... assigning it with a new value won't change the value of the original reference ... just what s points to ...
Besides, strings are immutable in most langs, meaning that you cannot change the value after being created.. they have to be recreated as new ones... so you will never see any change in the actual string ...