Überprüfen Sie, ob eine Variable eine Zeichenfolge in Ruby ist

124

Gibt es etwas Idiomatischeres als das Folgende?

foo.class == String
Davidkammern
quelle

Antworten:

205

Ich denke du suchst instance_of?. is_a?und kind_of?gibt true für Instanzen aus abgeleiteten Klassen zurück.

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
quelle
9
Ohne die Absicht der Frage zu kennen, würde ich sagen, dass für die meisten realen Programmiersituationen is_a?tatsächlich die geeignetere Redewendung verwendet wird (und oft ist eine Überprüfung der Ententypisierung, wie sie Andrew Grimm erwähnt, sogar noch besser). Ein strenger Klassenvergleich ist normalerweise ein Codegeruch. en.wikipedia.org/wiki/Liskov_substitution_principle
Mahemoff
Schnell beiseite: Wenn Sie dies in der bedingten Logik verwenden, müssen Sie Klammern verwenden. zB wenn foo.is_a? (String) && ...
dan
Wie erwartet funktioniert dieser Ansatz nicht nur mit String, sondern auch mit Integerund Float. Funktioniert es auch für Decimal? (Der erhabene Textinterpreter hebt die Syntax anders hervor Decimal, was mich misstrauisch macht)
Stevec
29

Ein Ansatz, bei dem mehr Enten geschrieben werden, wäre zu sagen

foo.respond_to?(:to_str)

to_str gibt an, dass die Klasse eines Objekts möglicherweise kein tatsächlicher Nachkomme des Strings ist, das Objekt selbst jedoch sehr stringartig (stringy?) ist.

Andrew Grimm
quelle
Cool. In diesem Fall passiere ich zu wissen , dass fooentweder sein true, falseoder eine Vanille-Saite, aber es ist gut allgemeinere Lösungen zu erfahren.
Davidchambers
Kombinieren Sie dies mit einem to_s-Aufruf, nachdem Sie überprüft haben, ob das Objekt darauf reagiert, und Sie haben sich einen String besorgt!
Seanmakesgames
1
@seanmakesgames Meinten Sie to_stroder to_s? Die beiden sind etwas unterschiedlich.
Andrew Grimm
stackoverflow.com/questions/11182052/… Re: andrews Kommentar.
Seanmakesgames
23

Du kannst tun:

foo.instance_of?(String)

Und das allgemeinere:

foo.kind_of?(String)
Federico Builes
quelle
4
Was macht kind_ofallgemeiner? Sie scheinen synonym zu sein : is_a.
Davidchambers
2
@ Davidchambers du hast recht, 'kind_of?' ist ein Synonym für 'is_a?'.
Steenslag
@davidchambers: Du hast recht, ich meinte instance_of?statt is_a?.
Federico Builes
7
foo.instance_of? String

oder

foo.kind_of? String 

Wenn es Sie nur interessiert, wenn es von Stringirgendwo in seiner Vererbungskette stammt

Matthew
quelle
4

Zusätzlich zu den anderen Antworten definiert Class die Methode ===, um zu testen, ob ein Objekt eine Instanz dieser Klasse ist.

  • o.class Klasse o.
  • o.instance_of? c bestimmt, ob o.class == c
  • o.is_a? c Ist o eine Instanz von c oder einer seiner Unterklassen?
  • o.kind_of? c Synonym für * is_a? *
  • c === o Bestimmen Sie für eine Klasse oder ein Modul, ob * o.is_a? c * ( String === "s" gibt true zurück)
steenslag
quelle
-1

Ich denke, ein besserer Weg ist es, einige Prädikatmethoden zu erstellen. Dadurch wird auch Ihr "Single Point of Control" gespeichert.

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

Je mehr Enten tippen;)

schlegel11
quelle
2
Was ist los mit "string".is_a?(String). Es scheint, als würden Sie das Rad neu erfinden. Es gibt auch class, instance_of, kind_ofusw ... Schlechte Idee zu Affen - Patch der ObjectKlasse, nicht zu erwähnen , es unnötig ist.
Mohamad
Ich stimme dir vollkommen zu :) Wenn du dich nur auf primitive Typen konzentrierst und du weißt, dass sich deine Projektanforderungen in Bezug auf primitive Typen niemals ändern werden (ok, das ist normalerweise der Fall;)), geht es dir gut. In einem Fall, in dem sich die Anforderungen ändern, ist es jedoch besser, einen "Single Point of Control" zu haben. Zum Beispiel haben Sie in Ihrer Projektumgebung viele Vorabprüfungen (1000 und höher). pre_check("test".is_string?) Jetzt ändert sich Ihre Projektanforderung und jeder String mit drei oder mehr Zeichen wird nicht mehr als String definiert (ich weiß, dass es ungewöhnlich ist;)). Jetzt können Sie Ihre eigene Methode einfach ändern.
schlegel11