67

我正在学习 Ruby,我看到了一些让我有点困惑的方法,尤其是to_svs to_str(以及类似的to_i/ to_intto_a/ to_ary、 & to_h/ to_hash)。我读过的内容解释了较短的形式(例如to_s)用于显式转换,而较长的形式用于隐式转换。

我真的不明白如何to_str实际使用。字符串以外的东西会定义to_str吗?你能给出这个方法的实际应用吗?

4

3 回答 3

81

首先请注意,所有这些都适用于 Ruby 中的每一对“短”(例如to_s/ to_i/ to_a/ to_h)与“长”(例如to_str/ to_int/ to_ary/ to_hash)强制方法(对于它们各自的类型),因为它们都具有相同的语义。


它们有不同的含义。你不应该实现to_str,除非你的对象一个字符串,而不是仅仅由一个字符串表示。唯一实现的核心类to_str是 String 本身。

来自Programming Ruby(引自这篇博文,值得一读):

[to_ito_s] 不是特别严格:例如,如果一个对象具有某种体面的字符串表示形式,它可能会有一个to_s方法…… [to_intto_str] 是严格的转换函数:只有当 [您的] 对象可以自然地实现它们时,您才能实现它们在每个可以使用字符串或整数的地方使用。

Pickaxe 中较旧的 Ruby 文档有这样的说法:

几乎所有类都支持的不同to_sto_str通常仅由那些行为类似于字符串的类实现。

例如,除了Integer之外,FloatNumeric都实现了to_int(to_i的等价物to_str),因为它们都可以很容易地替换 Integer (它们实际上都是数字)。除非你的类与 String 有同样紧密的关系,否则你不应该实现to_str.

于 2012-06-24T23:55:04.233 回答
24

要了解您是否应该使用/实现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"(即使该字符串不会被着色),那么to_str在 ColoredString 上实现。

于 2014-10-28T13:59:42.173 回答
0

Zverok有一篇很好理解的文章,关于何时使用什么(用 to_h 和 to_hash 解释)。

实现这些方法的对象是否可以转换为字符串 -> 使用to_s
或者它是某种(增强的)字符串的类型 -> 使用to_str


我在 gem 'configuration'GitHubConfiguration.rb)中看到了to_hashConfiguration 类在实践中的有意义的用法

它代表——顾名思义——提供的配置,实际上是一种散列(具有附加功能),而不是可转换为散列。

于 2019-02-27T13:15:04.737 回答