Sprawdź, czy zmienna jest łańcuchem w Rubim

124

Czy jest coś bardziej idiomatycznego niż poniższe?

foo.class == String
davidchambers
źródło

Odpowiedzi:

206

Myślę, że szukasz instance_of?. is_a?i kind_of?zwróci wartość true dla wystąpień z klas pochodnych.

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
Kandyd
źródło
9
Nie znając intencji pytania, powiedziałbym, że w przypadku większości rzeczywistych sytuacji programistycznych is_a?jest w rzeczywistości bardziej odpowiednim idiomem (a często sprawdzanie pisania na klawiaturze, o którym wspomina Andrew Grimm, jest jeszcze lepsze). Ścisłe porównanie klas to zwykle zapach kodu. en.wikipedia.org/wiki/Liskov_substitution_principle
mahemoff
Krótko na bok: jeśli używasz tego w logice warunkowej, musisz użyć nawiasów; np. jeśli foo.is_a? (String) && ...
dan
Zgodnie z oczekiwaniami to podejście będzie działać nie tylko z String, ale także z Integeri Float. Czy to też działa Decimal? (wzniosły interpreter tekstu inaczej podkreśla składnię, Decimalco sprawia, że ​​jestem podejrzliwy)
stevec
29

Można by powiedzieć, że bardziej typowe byłoby podejście do pisania na klawiaturze

foo.respond_to?(:to_str)

to_str wskazuje, że klasa obiektu może nie być rzeczywistym potomkiem String, ale sam obiekt jest bardzo podobny do ciągu (stringy?).

Andrew Grimm
źródło
Chłodny. W tym przypadku zdarza mi się, że fooalbo będzie true, falsealbo ciąg wanilia, ale to dobrze, aby dowiedzieć się więcej ogólnych rozwiązań.
davidchambers
połącz to z wywołaniem to_s po sprawdzeniu, czy obiekt na niego odpowiada, a otrzymasz łańcuch!
seanmakesgames
1
@seanmakesgames Miałeś na myśli to_str, czy to_s? Te dwa są nieco inne.
Andrew Grimm,
stackoverflow.com/questions/11182052/… Re: komentarz andrew.
seanmakesgames
23

Możesz to zrobić:

foo.instance_of?(String)

A bardziej ogólnie:

foo.kind_of?(String)
Federico Builes
źródło
4
Co jest kind_ofbardziej ogólne? Wydają się być synonimem: is_a.
davidchambers
2
@Davidchambers masz rację, „kind_of?” jest synonimem „is_a?”.
steenslag
@davidchambers: Masz rację, miałem na myśli instance_of?zamiast is_a?.
Federico Builes
7
foo.instance_of? String

lub

foo.kind_of? String 

jeśli obchodzi cię tylko to, że pochodzi z Stringjakiegoś miejsca w łańcuchu dziedziczenia

Mateusz
źródło
4

Oprócz innych odpowiedzi, Class definiuje metodę === do sprawdzania, czy obiekt jest instancją tej klasy.

  • o.class klasa o.
  • o.instance_of? c określa, czy o.class == c
  • o.is_a? c Czy o jest instancją klasy c lub którejkolwiek z jej podklas?
  • o.kind_of? c synonim * is_a? *
  • c === o dla klasy lub modułu, określ, czy * o.is_a? c * ( String === "s" zwraca prawdę)
steenslag
źródło
-1

Myślę, że lepszym sposobem jest stworzenie metod predykatów. Spowoduje to również zapisanie „pojedynczego punktu kontroli”.

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

Im bardziej kaczkowy sposób pisania;)

schlegel11
źródło
2
co jest nie tak z "string".is_a?(String). Wygląda na to, że odkrywasz koło na nowo. Jest też class, instance_of, kind_of, itd ... zły pomysł, aby małpa patch Objectklasa, nie wspominając, że to niepotrzebny.
Mohamad
Całkowicie się z Tobą zgadzam :) Jeśli skupiasz się tylko na typach pierwotnych i wiesz, że wymagania twojego projektu związane z typami pierwotnymi nigdy się nie zmienią (ok, tak to zwykle bywa;)) jest dobrze. Ale w przypadku, gdy wymagania się zmieniają, lepiej jest mieć „pojedynczy punkt kontroli”. Na przykład w środowisku projektu masz wiele wstępnych kontroli (1000 i więcej). pre_check("test".is_string?) Teraz wymagania twojego projektu ulegną zmianie i każdy łańcuch z trzema lub więcej znakami nie jest już zdefiniowany jako String (wiem, że jest niezwykły;)) Teraz możesz łatwo zmienić własną metodę.
schlegel11