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
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_sigleton_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 ;)
It's been a long time since I asked this. In ruby 1.9+, there's a better way of doing this by using define_singleton_method
, as follows:
obj = SomeObject.new
obj.define_singleton_method(:new_method) do
"do some things"
end
Use instance_eval
:
obj = SomeObject.new
obj.instance_eval do
def new_method
puts 'do something new'
end
end
obj.new_method
> "do something new"
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"
Another way to use a Mixin
obj = SomeObject.new
class << obj
include AnotherModule
end
This includes all of the methods from AnotherModule
into the current object.