Question as to why a piece of code is slower than a similar solution

Working in a project I came across this bit of code…

class HashText
attr_reader :hash

  def initialize(hash)
    @hash = hash || {}
  end

  def text
    hash.map do |key, value|
      value_string = if value.is_a?(Hash)
                       HashText.new(value).text
                     elsif value.is_a?(Array)
                       value.join(', ')
                     else
                       value
                     end

      "#{key.to_s}: #{value_string}"
    end.join('; ')
 end

end

I immediately wondered why it wasn’t written as…

class Object
def text
to_s
end
end

class Array
def text
map(&:text).join(’, ')
end
end

class Hash
def text
map do |key, value|
“#{key.to_s}: #{value.text}”
end.join(’; ')
end
end

but running some benchmarks it seems the later method is about 50 times
slower than the current solution and I was just curious as to actually
why that is. Anyone have any answers?

EDIT:
I thought it might be because the latter solution actually runs .text on
every element of an array instead of just doing a join, but changing
that bit still nets the same results…

Just being curious: Do you still get the same difference in speed, if
you change the monkey-page in Object to

class Object
  def text
    self
  end
end

? The to_s is not needed here.

so changing to using self on Object, actually turned out to be even
slower.