在Ruby中to_s与to_str(to_i / to_a / to_h与to_int / to_ary / to_hash)
我正在学习Ruby,并且我看到了一些让我困惑的方法,特别是to_s
vs to_str
(以及类似to_i
/ to_int
, to_a
/ to_ary
和to_h
/ to_hash
)。 我读过的内容解释说,较短的格式(例如to_s
)用于显式转换,而较长的格式用于隐式转换。
我真的不明白如何to_str
实际上会被使用。 除了string以外的东西会定义to_str
吗? 你能给这个方法的实际应用吗?
注意,所有这些都适用于to_s
每一对“short”(例如to_s
/ to_i
/ to_a
/ to_h
)和“long”(例如to_str
/ to_int
/ to_ary
/ to_hash
)强制方法(分别为它们的types)他们都有相同的语义。
他们有不同的含义。 你不应该实现to_str
除非你的对象像一个string一样,而不是只能被一个string表示 。 唯一实现to_str
核心类是String本身。
从编程ruby (引自这篇博文 ,这是值得一读的):
[
to_i
和to_s
]并不是特别严格:如果一个对象具有某种forms的表示forms作为string,例如,它可能会有一个to_s
方法… [to_int
和to_str
]是严格的转换函数:只有在[你的]对象可以自然地在每个地方使用一个string或一个整数可以被使用。
Pickaxe的旧版Ruby文档有这样的说法:
与几乎所有类都支持的
to_s
不同,to_str
通常只能由像string那样的类来实现。
例如,除了Integer , Float和Numeric都实现to_int
( to_i
相当于to_str
),因为它们都可以很容易地替代Integer(它们实际上都是数字)。 除非你的类与String有类似的紧密关系,否则你不应该实现to_str
。
要了解是否应该使用/实现to_s
/ to_str
,我们来看一些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
很乐意把任何对象变成一个string。 另一方面, to_str
在参数看起来不像string时会产生错误 。
现在让我们看看Array#join
。
[1,2].join(',') # returns "1,2" [1,2].join(3) # fails, the argument does not look like a valid separator.
在joinArray#join
之前, Array#join
将数组中的项(不pipe它们是真实的)转换成string是很有用的,所以Array#join
对它们的调用to_s
。
但是,分隔符应该是一个string – 有人调用[1,2].join(3)
可能会犯一个错误 。 这就是为什么Array#join
在分隔符上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
来获取描述对象的string。 - 调用
to_str
来validation一个对象真的像一个string。 - 实现
to_s
当你可以build立一个描述你的对象的string。 - 当你的对象完全像string一样行为的时候实现
to_str
。
我认为你可以自己实现to_str
情况也许是一个ColoredString
类 – 一个附加了颜色的string。 如果你很清楚传递一个彩色的逗号并不是错误,并且应该导致"1,2"
(即使该string不会被着色),那么在 to_str
上执行to_str。