我正在学习Ruby,我看到了一些令我困惑的方法,特别是to_s
vs to_str
(同样地,to_i
/ {{1} },to_int
/ to_a
,& to_ary
/ to_h
)。我读过的内容解释了较短的表单(例如to_hash
)用于显式转换,而较长的表单用于隐式转换。
我真的不明白实际使用to_s
的方式。除了字符串以外的东西会定义to_str
吗?你能为这种方法提供实际应用吗?
答案 0 :(得分:75)
首先请注意,所有这些都适用于每对“短”(例如to_s
/ to_i
/ to_a
/ to_h
)与“长”(例如to_str
/ to_int
/ to_ary
/ to_hash
)Ruby中的强制方法(针对各自的类型),因为它们都具有相同的语义。
他们有不同的含义。您不应该实现to_str
,除非您的对象像字符串一样,而不是仅仅通过字符串表示。实现to_str
的唯一核心类是String本身。
来自编程Ruby (引自this blog post,值得一读):
[
to_i
和to_s
]并不是特别严格:例如,如果一个对象具有某种正常的表示形式,那么它可能会有一个to_s
方法... [to_int
和to_str
]是严格的转换函数:只有在[your]对象可以自然地在每个地方使用字符串或整数时才能实现它们。
Older Ruby documentation from the Pickaxe有这样的说法:
与几乎所有类都支持的
to_s
不同,to_str
通常只由那些充当字符串的类实现。
例如,除了Integer之外,还有Float& Numeric实现to_int
(to_i
相当于to_str
),因为它们都可以轻松替换整数(它们实际上都是数字)。除非您的类与String具有类似的紧密关系,否则不应实现to_str
。
答案 1 :(得分:18)
要了解您是否应该使用/实施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
正如我们所看到的,to_s
很乐意将任何对象转换为字符串。另一方面,to_str
在其参数看起来不像字符串时会引发错误。
现在让我们看一下Array#join
。
[1,2].join(',') # returns "1,2"
[1,2].join(3) # fails, the argument does not look like a valid separator.
Array#join
在加入数组之前将其转换为字符串中的项目(无论它们是什么),这很有用,因此Array#join
会在其上调用to_s
。
但是,分隔符应该是一个字符串 - 有人调用[1,2].join(3)
可能会犯错误。这就是Array#join
在分隔符上调用to_str
的原因。
同样的原则似乎适用于其他方法。在哈希上考虑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.
总之,以下是我的看法:
to_s
以获取描述该对象的字符串。to_str
来验证对象是否真的像字符串一样。to_s
。to_str
。我认为你自己实现to_str
的情况可能是一个ColoredString
类 - 一个附加了颜色的字符串。如果您觉得将彩色逗号传递给join
并不是一个错误并且应该导致"1,2"
(即使该字符串不会被着色),那么做在ColoredString上实现to_str
。
答案 2 :(得分:0)
Zverok上有一篇很好的文章,易于理解,何时使用(使用to_h和to_hash进行了解释。)
必须确定实现这些方法的Object是否可以转换为字符串
->使用to_s
还是某种(增强型)字符串的类型
->使用to_str
我在宝石'configuration'(GitHub和Configuration.rb)中看到Configuration类的to_hash
的实际用法
顾名思义,它表示所提供的配置,实际上是一种哈希(具有附加功能),而不是可以转换为一个。