Ruby: Kind_Of? Vs. Instance_Of? Vs. Is_A

Ruby: kind_of? vs. instance_of? vs. is_a?

kind_of? and is_a? are synonymous.

instance_of? is different from the other two in that it only returns true if the object is an instance of that exact class, not a subclass.

Example:

  • "hello".is_a? Object and "hello".kind_of? Object return true because "hello" is a String and String is a subclass of Object.
  • However "hello".instance_of? Object returns false.

Performance difference between is_a? / kind_of? vs class.name for class comparison in ruby

I would argue is_a? is the correct one. Not because of performance but because of correctness.

Because it is perfectly fine to have multiple String classes in your app, it is not enough to just compare the class name. .class.name == 'String' only returns if the name of the class is "String", but it doesn't tell if it is the same String class that will be returned when you call String in the current context.

Whereas kind_of? does not only check if a is an instance of String. It would also return true if a is an instance of a subclass of String.

You asked about what approach is most efficient but did not tell how you define efficient in the context of your question. is_a? is the shortest, I would argue that is efficient. When you were thinking about performance, have a look at this:

require 'benchmark/ips'

string = "123"

Benchmark.ips do |x|
x.report("name == name") { string.class.name == "String" }
x.report("kind_of?") { string.kind_of?(String) }
x.report("is_a?") { string.is_a?(String) }
end

Warming up --------------------------------------
name == name 585.361k i/100ms
kind_of? 1.173M i/100ms
is_a? 1.299M i/100ms
Calculating -------------------------------------
name == name 5.870M (± 4.6%) i/s - 29.853M in 5.099899s
kind_of? 12.803M (± 3.0%) i/s - 64.514M in 5.043457s
is_a? 12.971M (± 3.6%) i/s - 64.935M in 5.012808s

Ruby: is_a? and instance_of? in BasicObject

You can steal is_a? from Kernel:

class My < BasicObject
define_method(:is_a?, ::Kernel.method(:is_a?))
end

m = My.new
m.is_a?(My) #=> true
m.is_a?(BasicObject) #=> true
m.is_a?(Object) #=> false

If you're going to build your own object hierarchy, you could also define your own Kernel, something like:

module MyKernel
[:is_a?, :instance_of?, :class].each do |m|
define_method(m, ::Kernel.method(m))
end
end

class My < BasicObject
include ::MyKernel
end

is there a proper way to use is_a? with an instance_double?

I would do:

let(:response) { instance_double(Net::HTTPOK, :body => 'nice body!', :code => 200) }
before { allow(response).to receive(:is_a?).with(Net::HTTPOK).and_return(true) }

Count class instances in array

You can use Enumerable#grep to fetch the instances of Car:

array.grep(Car).size

Ruby - Instance_of? / is_a not working

Try:

if new_item.is_a?(classA)
@items << new_item
end

is_a? is a method which returns true or false. As every method in ruby it can take a block, and as most of the methods it does absolutely nothing with it. So your << has never been executed.



Related Topics



Leave a reply



Submit