Add method to an instanced object
In ruby 1.9+, there's a better way of doing this using define_singleton_method
, as follows:
obj = SomeObject.new
obj.define_singleton_method(:new_method) do
"do some things"
end
There are several ways to achieve this, and they are all related to the singleton class:
You can use
class <<
idiom to open the singleton class definition:obj = Object.new class << obj def my_new_method ... end end
Or you can use
define_singleton_method
on the obj:obj = Object.new obj.define_singleton_method(:my_new_method) do ... end
You can also use
define_method
from the singleton class:obj = Object.new obj.singleton_class.define_method(:my_new_method) do ... end
Or you can use
def
directly:obj = Object.new def obj.my_new_method ... end
Pay attention to example 3, I think the concept of a singleton class becomes clearer on that one. There is a difference between these two examples:
a = Object.new
b = Object.new
# -- defining a new method in the object's "class" --
a.class.define_method(:abc) do
puts "hello abc"
end
a.abc # prints "hello abc"
b.abc # also prints "hello abc"
# -- defining a new method in the object's "singleton class" --
a.singleton_class.define_method(:bcd) do
puts "hello bcd"
end
a.bcd # prints "hello bcd"
b.bcd # error undefined method
This is because every object has its own singleton class:
a = Object.new
b = Object.new
p a.class # prints "Object"
p a.singleton_class # prints "#<Class:#<Object:0x000055ebc0b84438>>"
p b.class # also prints "Object"
p b.singleton_class # prints "#<Class:#<Object:0x000055ebc0b84410>>" (a different reference address)
Just an interesting point to note:
if you had instead gone:
def my_method
def my_other_method; end
end
Then my_other_method
would actually be defined on the CLASS of the object not withstanding that the receiver ofmy_method
is an instance.
However if you go (as you did):
def my_method
def self.my_other_method; end
end
Then my_other_method
is defined on the eigenclass of the instance.
Not directly relevant to your question but kind of interesting nonetheless ;)
Use a Mixin.
module AdditionalMethods
def new_method
"do some things"
end
end
obj = SomeObject.new
obj.extend(AdditionalMethods)
puts obj.new_method
> "do some things"