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