Add method to an instanced object
obj = SomeObject.new
def obj.new_method
"do some things"
end
puts obj.new_method
> "do some things"
This works ok. However, I need to do same thing inside an existing method:
def some_random_method
def obj.new_method
"do some things"
end
end
Works ok as well, but having a method inside a method looks pretty horrible. The question is, is there any alternate way of adding such a method?
Solution 1:
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
Solution 2:
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"
Solution 3:
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)