Add method to an instanced object

后端 未结 8 1740
眼角桃花
眼角桃花 2020-12-08 09:44
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

相关标签:
8条回答
  • 2020-12-08 09:51

    There are several ways to achieve this, and they are all related to the singleton class:

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

      obj = Object.new
      class << obj
        def my_new_method
           ...
        end
      end
      
    2. Or you can use define_singleton_method on the 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 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)
    
    0 讨论(0)
  • 2020-12-08 09:51

    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 ;)

    0 讨论(0)
  • 2020-12-08 09:52

    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
    
    0 讨论(0)
  • 2020-12-08 09:54

    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"
    
    0 讨论(0)
  • 2020-12-08 09:56

    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"
    
    0 讨论(0)
  • 2020-12-08 09:56

    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.

    0 讨论(0)
提交回复
热议问题