Чтобы понять, следует ли использовать / реализовать 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.