Ruby, adding methods to a Module, Class or Object -


i noticed odd while adding methods kernel make them available globally. it's interesting, , i'm looking documentation or explanation.

let's @ code:

file: ./demo.rb

# example 1  module kernel   def foo     puts "i'm defined inside module!"   end end   # example 2  module bar   def bar     puts "i'm included! (bar)"   end end  kernel.send :include, bar   # example 3  module baz   def baz     puts "i'm included! (baz)"   end end  module kernel   include baz end 

then, in bash , irb

$ irb -r ./demo.rb > foo # i'm defined inside module! > bar # nameerror: undefined local variable or method `bar' main:object > baz # nameerror: undefined local variable or method `baz' main:object > > self.class.ancestors # => [object, kernel, basicobject]  > > include kernel > > self.class.ancestors # => [object, kernel, baz, bar, basicobject] > > foo # i'm defined inside module! > bar # i'm included! (bar) > baz # i'm included! (baz) 

foo works expected, , available objects include kernel. bar , baz, on other hand, not available.
imagine it's because evaluation context of irb (an object) includes kernel, , including module inside module b not "reload" previous inclusions of b.
ok, makes perfect sense, , in fact re-including kernel add other 2 methods.

then, questions are:

  1. why opening kernel work? (example 1)
  2. if opening module treated differently, why isn't 3rd example working well?

what happens call foo.bar in ruby? this:

foo.class.ancestors.each |klass|   if klass.public_instance_methods.include? :bar     return klass.instance_method(:bar).bind(foo).call   end end raise nameerror 

i.e. ruby searches through ancestors find matching instance method.

and happens when call a.include b in ruby? this:

b.ancestors.each |mod|   a.ancestors << mod unless a.ancestors.include? mod end 

b , of ancestors become ancestors of a. these 2 behaviors explain everything:

  1. opening kernel works because it's included in object , ancestor of every object, meaning methods (including new ones) can searched whenever call method on object.
  2. opening module isn't treated differently. second , third examples same. both don't work because kernel's ancestors searched when included, before added new ancestors it.

Comments

Popular posts from this blog

java - Could not locate OpenAL library -

c++ - Delete matches in OpenCV (Keypoints and descriptors) -

sorting - opencl Bitonic sort with 64 bits keys -