skip to content

In Ruby, how do is_a?, kind_of? and instance_of? differ when you check an object's class?

level: juniorimportance: must knowfreq 62%

answer

  1. is_a? and kind_of? are aliases
  2. superclasses and included modules count
  3. instance_of? wants the exact class
  4. extended modules count for is_a?
  5. non-class argument: TypeError

basics

~20 s

is_a? and kind_of? are the same method: true when the class is the object's class, a superclass, or a module mixed into it. instance_of? is true only for the object's exact class, so subclasses and modules return false.

solid answer

~40 s

`is_a?` and `kind_of?` are aliases defined by `Kernel` with the same C function. They walk the object's ancestors, so `5.is_a?(Integer)`, `5.is_a?(Numeric)` and `5.is_a?(Comparable)` are all `true`, and a module added to one object with `extend` counts too. `instance_of?` compares the exact class: `5.instance_of?(Integer)` is `true` but `5.instance_of?(Numeric)` is `false`, and it is always `false` for a module. Both raise `TypeError` ("class or module required") when given something that is not a class or module. RuboCop's `Style/ClassCheck` makes a codebase pick one of `is_a?` or `kind_of?`, and `Style/ClassEqualityComparison` flags `obj.class == Foo` in favour of `instance_of?`. In practice `is_a?` is the usual choice, because `instance_of?` rejects subclasses that should be accepted.

code

ruby · 13 lines
ruby
5.is_a?(Integer)         # => true
5.kind_of?(Numeric)      # => true, same method as is_a?
5.is_a?(Comparable)      # => true, module included in Integer's ancestry
5.instance_of?(Integer)  # => true
5.instance_of?(Numeric)  # => false, exact class only

module Exportable; end
row = Object.new
row.extend(Exportable)
row.is_a?(Exportable)    # => true, extend counts
row.instance_of?(Object) # => true

5.is_a?("Integer")       # TypeError: class or module required

go deeper

for a junior

Recall that is_a? and kind_of? are the same and accept superclasses and modules, while instance_of? needs the exact class.

for a middle

Explain that is_a? walks the ancestors, including extended modules, and why instance_of? is always false for a module or a parent class.

for a senior

Justify is_a? over instance_of? when a check is needed, and know which RuboCop cops keep class checks consistent in a codebase.

for a principal

Decide where a codebase allows class checks at all, and how that interacts with proxies, decorators and subclassing in shared libraries.

## Two questions you can ask about an object's class Ruby gives every object three predicate methods from `Kernel` for asking about its class: - **`is_a?(mod)`** and **`kind_of?(mod)`**: two names for one method. "Is this object an instance of `mod`, or of something that inherits from or mixes in `mod`?" - **`instance_of?(klass)`**: "Is this object's class exactly `klass`?" Both kinds take a class or a module and return `true` or `false`. ## What is_a? looks at `is_a?` searches the object's **ancestors**: 1. the object's own class; 2. every superclass up to `BasicObject`; 3. every module included or prepended into any of those classes; 4. modules added to this one object with `extend`, because the search starts from the object's singleton class when it has one. So for `5`: `is_a?(Integer)`, `is_a?(Numeric)`, `is_a?(Comparable)`, `is_a?(Object)` and `is_a?(Kernel)` are all `true`. The Ruby documentation's example uses a class `B < A` where `A` includes a module `M`: a `B` instance is `is_a?` `A`, `B` and `M`, but not `C` (a subclass of `B`). ## What instance_of? looks at `instance_of?` ignores ancestry completely. It compares the object's class (ignoring any singleton class) with the argument: | Expression | `is_a?` | `instance_of?` | |---|---|---| | `5` vs `Integer` | `true` | `true` | | `5` vs `Numeric` | `true` | `false` | | `5` vs `Comparable` (a module) | `true` | `false` | | `Set[1]` vs `Enumerable` | `true` | `false` | | `B.new` vs `A`, where `B < A` | `true` | `false` | Because a module is never an object's class, `instance_of?` with a module is always `false`. ## Errors and edge cases - Passing something that is not a class or module, such as a String naming a class, raises **`TypeError`** with the message `class or module required`. - `obj.class == Foo` behaves like `instance_of?` but reads worse; RuboCop's **`Style/ClassEqualityComparison`** cop flags it and suggests `instance_of?` (it allows the pattern inside `==`, `equal?` and `eql?` definitions by default). - RuboCop's **`Style/ClassCheck`** cop enforces one spelling across a codebase, `is_a?` by default. ## Which one to use - **`is_a?`** is the normal choice when a class check is justified. It accepts subclasses, which is what the Liskov-style contract of inheritance promises callers. - **`instance_of?`** is for the rare case where a subclass must be treated differently from its parent, for example an exact-type check in serialization code. - **Neither** is the first choice in everyday Ruby. Most methods should call the method they need and let any object that implements it through; class checks reject objects such as proxies, decorators and custom collections that would have worked. ## Common mistakes - Believing `kind_of?` is looser or stricter than `is_a?`. They are the same method under two names. - Using `instance_of?(Numeric)` to accept numbers: it rejects every Integer and Float, because their classes are subclasses of `Numeric`. - Checking `is_a?(Array)` to accept "a collection": it rejects `Set`, `Enumerator`, `Hash` and any custom class with `each`, which is exactly where the duck-typing discussion starts. ## In an interview A strong answer states the two rules, gives one example of each diverging (`5.is_a?(Numeric)` true, `5.instance_of?(Numeric)` false), and then adds the judgement: both checks couple code to class names, so idiomatic Ruby reaches for them only when calling the needed method directly is not enough. Mentioning that `kind_of?` is just another spelling of `is_a?` and that `extend` affects `is_a?` shows you know the mechanics, not only the vocabulary. ## A quick mental model Think of `is_a?` as "does this class or module appear anywhere in the object's family tree" and `instance_of?` as "is this the name on the object's own birth certificate". The tree includes mixed-in modules; the certificate never does.

  • Does a module added with `extend` make `is_a?` return true, and does it affect `instance_of?`?
    `is_a?` returns true, because the search starts from the object's singleton class, whose ancestors include the extended module. `instance_of?` is unaffected: it compares the object's real class, skipping the singleton class, and a module can never be that class.
  • Why does RuboCop prefer `instance_of?` over `obj.class == Foo`?
    They test the same thing, exact class identity, but `instance_of?` states the intent directly. `Style/ClassEqualityComparison` flags the comparison forms, including `obj.class.name == "Foo"`, and by default leaves them alone inside `==`, `equal?` and `eql?` definitions, where comparing classes is the usual idiom.

saying these in an interview costs you the question

  • kind_of? also accepts superclasses while is_a? checks only the exact class.
  • instance_of? returns true for a parent class of the object.
  • is_a? ignores modules, so 5.is_a?(Comparable) is false.
  • instance_of?(Numeric) is a good way to accept any number.
  • Passing a class name String to is_a? works like passing the class.