"do some things" This is wo...">

Add method to instantiated object

obj = SomeObject.new def obj.new_method "do some things" end puts obj.new_method > "do some things" 

This is working fine. However, I need to do the same inside an existing method:

 def some_random_method def obj.new_method "do some things" end end 

It works fine, but the method inside the method looks pretty awful. The question is, is there an alternative way to add such a method?

+49
ruby
Dec 11 '09 at 12:43
source share
7 answers

It has been a long time since I asked about this. In ruby ​​1.9+, the best way to do this is using define_singleton_method , as follows:

 obj = SomeObject.new obj.define_singleton_method(:new_method) do "do some things" end 
+73
Oct 11 '12 at 14:25
source share

Use Mixin.

 module AdditionalMethods def new_method "do some things" end end obj = SomeObject.new obj.extend(AdditionalMethods) puts obj.new_method > "do some things" 
+48
Dec 11 '09 at 12:48
source share

Just interesting to note:

if you left:

 def my_method def my_other_method; end end 

Then my_other_method will be actually defined in the object's my_other_method , not allowing the receiver my_method be an instance.

However, if you go (like you):

 def my_method def self.my_other_method; end end 

Then my_other_method defined on the instance's own instance.

It is not directly related to your question, but, nevertheless, is interesting;)

+7
Dec 11 '09 at 15:27
source share

You can use modules.

 module ObjSingletonMethods def new_method "do some things" end end obj.extend ObjSingletonMethods puts obj.new_method # => do some things 

Now, if you need to add additional methods to this object, you just need to implement the methods in the module, and you are done.

+6
Dec 11 '09 at 12:50
source share
 class Some end obj = Some.new class << obj def hello puts 'hello' end end obj.hello obj2 = Some.new obj2.hello # error 

class << obj syntax class << obj means that we open the class definition for the object. As you probably know, we can define Ruby class methods using the syntax as follows:

 class Math class << self def cos(x) ... end def sin(x) ... end end end 

Then we can use the following methods:

 Math.cos(1) 

In Ruby, all objects - even classes. self here is an object of the Math class (you can access this object using Math.class ). Thus, the class << self syntax of the class << self means that we open the class for the Math class object of the Math class object . Yes, that means the Math class has a class (Math.class.class).

+1
Mar 29 '18 at 22:29
source share

There are several syntaxes for this, and they are all associated with the singleton class:

  1. You can use class << idiom to open a singleton class definition:

     obj = Object.new class << obj def my_new_method ... end end 
  2. Or you can use define_singleton_method for obj:

     obj = Object.new obj.define_sigleton_method(:my_new_method) do ... end 
  3. You can also use define_method from the singleton class:

     obj = Object.new obj.singleton_class.define_method(:my_new_method) do ... end 
  4. Or you can directly use def :

     obj = Object.new def obj.my_new_method ... end 

Pay attention to example 3, I think that the concept of a singleton class becomes more understandable for this. There is a difference between the two examples:

  a = Object.new b = Object.new # -- defining a new method in the object "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 "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 due to the fact that each 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) 
+1
May 04 '18 at 19:19
source share

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" 
+1
Jul 14 '18 at 4:37
source share



All Articles