Ruby 中的 to_s 与 to_str(以及 to_i/to_a/to_h 与 to_int/to_ary/to_hash)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11182052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
to_s vs. to_str (and to_i/to_a/to_h vs. to_int/to_ary/to_hash) in Ruby
提问by Jeff Storey
I'm learning Ruby and I've seen a couple of methods that are confusing me a bit, particularly to_svs to_str(and similarly, to_i/to_int, to_a/to_ary, & to_h/to_hash). What I've read explains that the shorter form (e.g. to_s) are for explicit conversions while the longer form are for implicit conversions.
我正在学习 Ruby,并且我看到了一些让我有点困惑的方法,特别是to_svs to_str(类似地,to_i/ to_int、to_a/ to_ary、 & to_h/ to_hash)。我读过的内容解释说,较短的形式(例如to_s)用于显式转换,而较长的形式用于隐式转换。
I don't really understand how to_strwould actually be used. Would something other than a String ever define to_str? Can you give a practical application for this method?
我真的不明白如何to_str实际使用。除了 String 之外的其他东西会定义to_str吗?你能给出这个方法的实际应用吗?
回答by Andrew Marshall
Note first that all of this applies to each pair of “short” (e.g. to_s/to_i/to_a/to_h) vs. “long” (e.g. to_str/to_int/to_ary/to_hash) coercion methods in Ruby (for their respective types) as they all have the same semantics.
首先请注意,所有这些都适用于 Ruby 中的每一对“短”(例如to_s/ to_i/ to_a/ to_h)与“长”(例如to_str/ to_int/ to_ary/ to_hash)强制转换方法(针对它们各自的类型),因为它们都具有相同的语义。
They have different meanings. You should not implement to_strunless your object actslike a string, rather than just being representableby a string. The only core class that implements to_stris String itself.
它们有不同的含义。to_str除非您的对象表现得像一个字符串,而不仅仅是由字符串表示,否则您不应该实现。唯一实现的核心类to_str是 String 本身。
From Programming Ruby(quoted from this blog post, which is worth reading all of):
来自Programming Ruby(引自这篇博文,值得一读):
[
to_iandto_s] are not particularly strict: if an object has some kind of decent representation as a string, for example, it will probably have ato_smethod… [to_intandto_str] are strict conversion functions: you implement them only if [your] object can naturally be used every place a string or an integer could be used.
[
to_i和to_s] 并不是特别严格:例如,如果一个对象有某种像样的表示形式,例如,它可能有一个to_s方法…… [to_int和to_str] 是严格的转换函数:只有当 [your] 对象可以自然地在可以使用字符串或整数的每个地方使用。
Older Ruby documentation from the Pickaxehas this to say:
Unlike
to_s, which is supported by almost all classes,to_stris normally implemented only by those classes that act like strings.
to_s几乎所有类都支持的不同,to_str通常仅由那些行为类似于字符串的类实现。
For example, in addition to Integer, both Float& Numericimplement to_int(to_i's equivalent of to_str) because both of them can readily substituted for an Integer (they are all actually numbers). Unless your class has a similarly tight relationship with String, you should not implement to_str.
例如,除了Integer 之外,Float和Numeric 都实现了to_int(to_i的等价于to_str) 因为它们都可以很容易地替换 Integer (它们实际上都是数字)。除非您的类与 String 具有类似的紧密关系,否则您不应实现to_str.
回答by Eldritch Conundrum
To understand if you should use/implement to_s/to_str, let's look at some exemples. It is revealing to consider when these method fail.
要了解是否应该使用/实现to_s/ to_str,让我们看一些示例。当这些方法失败时考虑是有启发性的。
1.to_s # returns "1"
Object.new.to_s # returns "#<Object:0x4932990>"
1.to_str # raises NoMethodError
Object.new.to_str # raises NoMethodError
As we can see, to_sis happy to turn any objectinto a string. On the other hand, to_strraises an errorwhen its parameter does not look like a string.
正如我们所见,to_s很高兴将任何对象变成字符串。另一方面,当其参数看起来不像字符串时to_str会引发错误。
Now let us look at Array#join.
现在让我们看看Array#join。
[1,2].join(',') # returns "1,2"
[1,2].join(3) # fails, the argument does not look like a valid separator.
It is useful that Array#joinconverts to string the items in the array (whatever they really are) before joining them, so Array#joincalls to_son them.
Array#join将数组中的项目(无论它们真正是什么)转换为字符串是很有用的,因此Array#join调用to_s它们。
However, the separator is supposed to be a string -- someone calling [1,2].join(3)is likely to be making a mistake. This is why Array#joincalls to_stron the separator.
然而,分隔符应该是一个字符串——有人打电话[1,2].join(3)可能会出错。这就是Array#join调用to_str分隔符的原因。
The same principle seems to hold for the other methods. Consider to_a/to_aryon a hash:
同样的原则似乎适用于其他方法。考虑to_a/to_ary在哈希上:
{1,2}.to_a # returns [[1, 2]], an array that describes the hash
{1,2}.to_ary # fails, because a hash is not really an array.
In summary, here is how I see it:
总之,这是我的看法:
- call
to_sto get a string that describes the object. - call
to_strto verify that an object really acts like a string. - implement
to_swhen you can build a string that describes your object. - implement
to_strwhen your object can fully behave like a string.
- 调用
to_s以获取描述对象的字符串。 - 调用
to_str以验证对象是否真的像字符串一样。 to_s当您可以构建描述您的对象的字符串时实现。to_str当您的对象可以完全像字符串一样运行时实现。
I think a case when you could implement to_stryourself is maybe a ColoredStringclass -- a string that has a color attached to it. If it seems clear to you that passing a colored comma to joinis not a mistake and should result in "1,2"(even though that string would not be colored), then doimplement to_stron ColoredString.
我认为你可以to_str自己实现的一个例子可能是一个ColoredString类——一个附加了颜色的字符串。如果它似乎昭示着你,传递一个彩色逗号join是不是一个错误,并且会导致"1,2"(即使该字符串不会被着色),然后就落实to_str上ColoredString。
回答by dCSeven
Zverokhas a great easily understandable article about when to use what (explained with to_h and to_hash).
Zverok有一篇很容易理解的文章,关于何时使用什么(用 to_h 和 to_hash 解释)。
It has to do whether your Object implementing those methods can be converted to a string
-> use to_s
or it is a type of some (enhanced) string
-> use to_str
实现这些方法的对象是否可以转换为字符串 -> 使用,to_s
或者它是某种(增强的)字符串的类型 -> 使用to_str
I've seen a meaningful usage of to_hashin practice for the Configuration class in the gem 'configuration'(GitHuband Configuration.rb)
我to_hash在 gem 'configuration'(GitHub和Configuration.rb)中看到了Configuration 类在实践中的有意义的用法
It represents -- as the name says -- the provided configuration, which in fact is a kind of hash (with additional features), rather than being convertible to one.
它代表——顾名思义——提供的配置,它实际上是一种散列(具有附加功能),而不是可转换为一个散列。

