The five statements
Let's consider those five statements one at a time (but in a different order than as presented). Note that send
's argument must be the name of the method expressed as a string or symbol.
SimpleModule.send("class_hello_world")
# i am a SimpleModule class method
This is normal, though such methods are normally called module methods. Some common built-in modules, such as Math, contain module methods only.
SimpleClass.send(:class_hello_world)
# i am a SimpleClass class method
Since a class is a module, the behaviour is the same as above. class_hello_world
is usually referred to as a class method.
SimpleClass.new.send(:hello_world)
# i am SimpleClass method
This is the normal invocation of an instance method.
SimpleModule.send("hello_world")
#=> NoMethodError: undefined method `hello_world' for SimpleModule:Module
There is no module method hello_world
.
SimpleModule.new.send(hello_world)
#=> NoMethodError: undefined method `new' for SimpleModule:Module
One cannot create an instance of a module.
include
vs prepend
Suppose one wrote
SimpleClass.include SimpleModule
#=> SimpleClass
SimpleClass.new.hello_world
# i am SimpleClass method
so SimpleClass
' original method hello_world
is not overwritten by the module's method by the same name. Consider SimpleClass
' ancestors.
SimpleClass.ancestors
#=> [SimpleClass, SimpleModule, Object, Kernel, BasicObject]
Ruby will look for hello_world
in SimpleClass
--and find it--before considering SimpleModule
.
One can, however, use Module#prepend to put SimpleModule#hello_world
before SimpleClass#hello_world
.
SimpleClass.prepend SimpleModule
#=> SimpleClass
SimpleClass.new.hello_world
# i am a SimpleModule method
SimpleClass.ancestors
#=> [SimpleModule, SimpleClass, Object, Kernel, BasicObject]
Binding unbound methods
There is one other thing you do. SimpleModule
's instance methods (here just one) are unbound. You could use UnboundMethod#bind to bind each to an instance of SimpleClass
and then execute it using call
or send
.
sc = SimpleClass.new
#=> #<SimpleClass:0x007fcbc2046010>
um = SimpleModule.instance_method(:hello_world)
#=> #<UnboundMethod: SimpleModule#hello_world>
bm = um.bind(sc)
#=> #<Method: SimpleModule#hello_world>
bm.call
#=> i am a SimpleModule method
sc.send(:hello_world)
#=> i am a SimpleModule method