J'apprends Ruby et j'ai vu quelques méthodes qui me déroutent un peu, en particulier to_s
contre to_str
(et de même, to_i
/to_int
, to_a
/to_ary
, & to_h
/to_hash
). Ce que j'ai lu explique que le formulaire plus court (par exemple to_s
) sont pour les conversions explicites tandis que la forme plus longue est pour les conversions implicites.
Je ne comprends pas vraiment comment to_str
serait effectivement utilisé. Est-ce que quelque chose d'autre qu'une chaîne définirait jamais to_str
? Pouvez-vous donner une application pratique pour cette méthode?
Notez d'abord que tout cela s'applique à chaque paire de "short" (par exemple to_s
/to_i
/to_a
/to_h
) vs "long" (par exemple to_str
/to_int
/to_ary
/to_hash
) méthodes de coercition dans Ruby (pour leurs types respectifs) car elles ont toutes la même sémantique.
Ils ont des significations différentes. Vous ne devez pas implémenter to_str
sauf si votre objet agit comme une chaîne, plutôt que d'être simplement représentable par une chaîne. La seule classe principale qui implémente to_str
est String lui-même.
De Programmation Ruby (cité de ce billet de blog , qui vaut la peine d'être lu tout):
[
to_i
etto_s
] ne sont pas particulièrement stricts: si un objet a une sorte de représentation décente sous forme de chaîne, par exemple, il aura probablement unto_s
méthode… [to_int
etto_str
] sont des fonctions de conversion strictes: vous ne les implémentez que si [votre] objet peut naturellement être utilisé à chaque endroit où une chaîne ou un entier pourrait être utilisé.
Ancienne Ruby de la pioche a ceci à dire:
Contrairement à
to_s
, qui est pris en charge par presque toutes les classes,to_str
n'est normalement implémenté que par les classes qui agissent comme des chaînes.
Par exemple, en plus de Entier , les deux Flottant & Numérique implémentent to_int
(to_i
est l'équivalent de to_str
) parce que les deux peuvent facilement remplacer un nombre entier (ils sont tous en fait des nombres). À moins que votre classe n'ait une relation similaire avec String, vous ne devez pas implémenter to_str
.
Pour comprendre si vous devez utiliser/implémenter to_s
/to_str
, Regardons quelques exemples. Il est révélateur de considérer lorsque ces méthodes échouent.
1.to_s # returns "1"
Object.new.to_s # returns "#<Object:0x4932990>"
1.to_str # raises NoMethodError
Object.new.to_str # raises NoMethodError
Comme nous pouvons le voir, to_s
Est heureux de transformer n'importe quel objet en une chaîne. D'un autre côté, to_str
déclenche une erreur lorsque son paramètre ne ressemble pas à une chaîne.
Voyons maintenant Array#join
.
[1,2].join(',') # returns "1,2"
[1,2].join(3) # fails, the argument does not look like a valid separator.
Il est utile que Array#join
Soit converti pour enchaîner les éléments du tableau (quels qu'ils soient réellement) avant de les joindre, donc Array#join
Appelle to_s
Sur eux.
Cependant, le séparateur est censé être une chaîne - quelqu'un qui appelle [1,2].join(3)
est susceptible de faire une erreur. C'est pourquoi Array#join
Appelle to_str
Sur le séparateur.
Le même principe semble s'appliquer aux autres méthodes. Considérez to_a
/to_ary
Sur un hachage:
{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.
En résumé, voici comment je le vois:
to_s
pour obtenir une chaîne décrivant l'objet.to_str
pour vérifier qu'un objet agit vraiment comme une chaîne.to_s
lorsque vous pouvez créer une chaîne décrivant votre objet.to_str
lorsque votre objet peut se comporter complètement comme une chaîne.Je pense qu'un cas où vous pourriez implémenter to_str
Vous-même est peut-être une classe ColoredString
- une chaîne qui a une couleur attachée. S'il vous semble clair que passer une virgule colorée à join
n'est pas une erreur et devrait entraîner "1,2"
(Même si cette chaîne ne serait pas colorée), alors faire implémenter to_str
sur ColoredString.
Zverok a un excellent article facilement compréhensible sur quand utiliser quoi (expliqué avec to_h et to_hash).
Il doit déterminer si votre objet implémentant ces méthodes peut être converti en chaîne -> utiliser to_s
ou il s'agit d'un type de chaîne (améliorée) -> utilisez to_str
J'ai vu une utilisation significative de to_hash
en pratique pour la classe Configuration dans la gemme 'configuration' ( GitHub et Configuration.rb )
Il représente - comme son nom l'indique - la configuration fournie, qui est en fait une sorte de hachage (avec des fonctionnalités supplémentaires), plutôt que d'être convertible en une seule.