159

Is there anything more idiomatic than the following?

foo.class == String
Nathan Kleyn
  • 5,103
  • 3
  • 32
  • 49
davidchambers
  • 23,918
  • 16
  • 76
  • 105

6 Answers6

254

I think you are looking for instance_of?. is_a? and kind_of? will return true for instances from derived classes.

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
  • 30,469
  • 8
  • 53
  • 60
  • 12
    Without knowing the question's intent, I'd say for most real-world programming situations, `is_a?` is actually the more appropriate idiom to use (and often a duck-typing check like Andrew Grimm mentions is even better). A strict class comparison is usually a code smell. http://en.wikipedia.org/wiki/Liskov_substitution_principle – mahemoff Jan 17 '13 at 06:23
  • 1
    Quick aside: if you use this in conditional logic you need to use parentheses; eg, if foo.is_a?(String) && ... – dan May 07 '18 at 20:03
  • As expected, this approach will work not only with `String`, but also with `Integer` and `Float`. Does it also work for `Decimal`? (the sublime text interpreter highlights the syntax differently for `Decimal` which makes me suspicious) – stevec Jan 27 '19 at 16:18
33

A more duck-typing approach would be to say

foo.respond_to?(:to_str)

to_str indicates that an object's class may not be an actual descendant of the String, but the object itself is very much string-like (stringy?).

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
32

You can do:

foo.instance_of?(String)

And the more general:

foo.kind_of?(String)
Milo P
  • 1,377
  • 2
  • 31
  • 40
Federico Builes
  • 4,939
  • 4
  • 34
  • 48
  • [davidchambers](https://stackoverflow.com/users/312785/davidchambers) and [steenslag](https://stackoverflow.com/users/290394/steenslag) noted that `kind_of?` is a synonym for [`is_a?`](http://ruby-doc.org/docs/ProgrammingRuby/html/ref_c_object.html#Object.is_a_qm). Unfortunately, including these comments as discussed for example [here](https://meta.stackoverflow.com/a/254530/4575793) was rejected. – Cadoiz Apr 04 '23 at 09:10
8
foo.instance_of? String

or

foo.kind_of? String 

if you you only care if it is derrived from String somewhere up its inheritance chain

Matthew
  • 12,892
  • 6
  • 42
  • 45
5

In addition to the other answers, Class defines the method === to test whether an object is an instance of that class.

  • o.class class of o.
  • o.instance_of? c determines whether o.class == c
  • c === o for a class or module, determine if o.is_a? c (String === "s" returns true)
  • o.is_a? c Is o an instance of c or any of it's subclasses?
  • o.kind_of? c synonym for is_a?
Cadoiz
  • 1,446
  • 21
  • 31
steenslag
  • 79,051
  • 16
  • 138
  • 171
-1

I think a better way is to create some predicate methods. This will also save your "Single Point of Control".

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

The more duck typing way ;)

schlegel11
  • 363
  • 4
  • 8
  • 2
    what's wrong with `"string".is_a?(String)`. It seems like you're reinventing the wheel. There's also `class`, `instance_of`, `kind_of`, etc... Bad idea to monkey patch the `Object` class, not to mention it's needless. – Mohamad Apr 24 '15 at 12:08
  • I totally agree with you :) If your focus is only on primitve types and you know that your project requirements related to primitive types will never change (ok its usually the case ;) ) youre fine. But in a case where requirements change its better to have a "Single Point of Control". For example in your project environment you have a lot of pre checks (1000 and up). `pre_check("test".is_string?)` Now your project requirement will change and every String with three characters or more is no longer defined as String (i know its unusual ;)) Now you can change your own method easily. – schlegel11 Apr 24 '15 at 14:27