Vérifiez si une variable est une chaîne dans Ruby

124

Y a-t-il quelque chose de plus idiomatique que ce qui suit?

foo.class == String
davidchambers
la source

Réponses:

205

Je pense que vous recherchez instance_of?. is_a?et kind_of?retournera true pour les instances de classes dérivées.

class X < String
end

foo = X.new

foo.is_a? String         # true
foo.kind_of? String      # true
foo.instance_of? String  # false
foo.instance_of? X       # true
Candide
la source
9
Sans connaître l'intention de la question, je dirais que pour la plupart des situations de programmation du monde réel, is_a?est en fait l'idiome le plus approprié à utiliser (et souvent une vérification de type canard comme Andrew Grimm le mentionne est encore meilleure). Une comparaison de classe stricte est généralement une odeur de code. en.wikipedia.org/wiki/Liskov_substitution_principle
mahemoff
À part: si vous utilisez ceci dans la logique conditionnelle, vous devez utiliser des parenthèses; par exemple, si foo.is_a? (String) && ...
dan
Comme prévu, cette approche fonctionnera non seulement avec String, mais aussi avec Integeret Float. Cela fonctionne-t-il aussi pour Decimal? (l'interprète de texte sublime met en évidence la syntaxe différemment pour Decimalce qui me rend suspect)
stevec
29

Une approche plus typée canard serait de dire

foo.respond_to?(:to_str)

to_str indique que la classe d'un objet n'est peut-être pas un descendant réel de String, mais que l'objet lui-même ressemble beaucoup à une chaîne (stringy?).

Andrew Grimm
la source
Cool. Dans ce cas , je sais que fooseront soit true, falseou une chaîne de vanille, mais il est bon d'apprendre des solutions plus générales.
davidchambers
combinez cela avec un appel to_s après avoir vérifié si l'objet y répond, et vous avez vous-même une chaîne!
seanmakesgames
1
@seanmakesgames Voulez-vous dire to_str, ou to_s? Les deux sont légèrement différents.
Andrew Grimm
stackoverflow.com/questions/11182052/… Re: commentaire d'Andrew.
seanmakesgames
23

Tu peux faire:

foo.instance_of?(String)

Et le plus général:

foo.kind_of?(String)
Federico Builes
la source
4
Qu'est-ce qui rend kind_ofplus général? Ils semblent être synonyme: is_a.
davidchambers
2
@Davidchambers vous avez raison, 'kind_of?' est un synonyme de «is_a?».
steenslag
@davidchambers: Vous avez raison, je voulais dire instance_of?au lieu de is_a?.
Federico Builes
7
foo.instance_of? String

ou

foo.kind_of? String 

si vous ne vous souciez que si elle est dérivée de Stringquelque part dans sa chaîne d'héritage

Matthieu
la source
4

En plus des autres réponses, Class définit la méthode === pour tester si un objet est une instance de cette classe.

  • o.class classe de o.
  • o.instance_of? c détermine si o.class == c
  • o.is_a? c Est-ce que o est une instance de c ou l'une de ses sous-classes?
  • o.kind_of? c synonyme de * is_a? *
  • c === o pour une classe ou un module, déterminez si * o.is_a? c * (la chaîne === "s" renvoie vrai)
Steenslag
la source
-1

Je pense qu'une meilleure façon est de créer des méthodes de prédicat. Cela permettra également de sauvegarder votre «point de contrôle unique».

class Object
 def is_string?
   false
 end
end

class String
 def is_string?
   true
 end
end

print "test".is_string? #=> true
print 1.is_string?      #=> false

Le moyen de frappe le plus canard;)

schlegel11
la source
2
quel est le problème avec "string".is_a?(String). Il semble que vous réinventez la roue. Il y a aussi class, instance_of, kind_of, etc ... mauvaise idée de patch singe la Objectclasse, pour ne pas mentionner qu'il est inutile.
Mohamad
Je suis totalement d'accord avec vous :) Si vous vous concentrez uniquement sur les types primitifs et que vous savez que les exigences de votre projet liées aux types primitifs ne changeront jamais (ok c'est généralement le cas;)) vous allez bien. Mais dans un cas où les exigences changent, il vaut mieux avoir un «point de contrôle unique». Par exemple, dans votre environnement de projet, vous avez beaucoup de pré-contrôles (1000 et plus). pre_check("test".is_string?) Maintenant, les exigences de votre projet vont changer et chaque chaîne de trois caractères ou plus n'est plus définie comme chaîne (je sais que c'est inhabituel;)) Vous pouvez maintenant changer votre propre méthode facilement.
schlegel11