к s и к (ул. и я/к/к H и к инт/до Ары/хэша) в Ruby


Я изучаю Ruby, и я видел несколько методов, которые меня немного смущают, особенно to_s vs to_str (и точно так же,to_i/to_int,to_a/to_ary,& to_h/to_hash). То, что я прочитал, объясняет, что более короткая форма (например,to_s) предназначены для явных преобразований, а более длинная форма - для неявных преобразований.

Я действительно не понимаю, как to_str будет фактически использоваться. Будет ли что-то другое, чем строка, когда-либо определять to_str? Вы можете дать практическое применение этому методу?

2 59

2 ответа:

обратите внимание, что все это относится к каждой паре "коротких" (например,to_s/to_i/to_a/to_h) и "длинные" (например,to_str/to_int/to_ary/to_hash) методы принуждения в Ruby (для их соответствующих типов), поскольку все они имеют одинаковую семантику.


они имеют разные значения. Вы не должны реализовывать to_str если ваш объект действия как строка, а не просто быть представимое строкой. Единственный основной класс это реализует to_str сама строка.

С Программирования Ruby (цитата из этот блог, который стоит прочитать всем):

[to_i и to_s] не особенно строгие: если объект имеет какое-то приличное представление в виде строки, например, он, вероятно, будет иметь to_s метод... [to_int и to_str] являются строгими функциями преобразования: вы реализуете их только в том случае, если [ваш] объект может быть естественным используется в каждом месте, где может использоваться строка или целое число.

старые рубиновые документы из кирки говорит:

в отличие от to_s, который поддерживается почти всеми классами,to_str обычно реализуется только теми классами, которые действуют как строки.

например, в дополнение к целое, и Float & цифровой реализовать to_int (to_i ' s эквивалент to_str) потому что оба они могут легко заменить целое число (все они на самом деле числа). Если ваш класс не имеет аналогичной тесной связи со строкой, вы не должны реализовывать to_str.

чтобы понять, если вы должны использовать/реализовать 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 на a хэш:

{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 class -- строка, к которой прикреплен цвет. Если вам кажется ясным, что передача цветной запятой в join это не ошибка и в результате "1,2" (даже если эта строка не будет окрашена), то do реализовать to_str на ColoredString.