将方法添加到实例化对象

时间:2009-12-11 12:43:33

标签: ruby

obj = SomeObject.new

def obj.new_method
  "do some things"
end

puts obj.new_method
> "do some things"

这没关系。但是,我需要在现有方法中做同样的事情:

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

也可以正常工作,但在方法中使用方法看起来非常可怕。问题是,有没有其他方法可以添加这样的方法?

8 个答案:

答案 0 :(得分:74)

我问这个问题已经很久了。在ruby 1.9+中,使用define_singleton_method有一种更好的方法,如下所示:

obj = SomeObject.new

obj.define_singleton_method(:new_method) do
  "do some things"
end

答案 1 :(得分:50)

使用Mixin。

module AdditionalMethods
  def new_method
    "do some things"
  end
end

obj = SomeObject.new
obj.extend(AdditionalMethods)

puts obj.new_method
> "do some things"

答案 2 :(得分:8)

只是一个有趣的注意事项:

如果你已经离开了:

def my_method
    def my_other_method; end
end

然后my_other_method实际上会在对象的CLASS上定义,而不是my_method的接收者是一个实例。

但是如果你去(就像你一样):

def my_method
    def self.my_other_method; end
end

然后在实例的本征类上定义my_other_method

与你的问题没有直接关系,但有点有趣;)

答案 3 :(得分:6)

您可以使用模块。

module ObjSingletonMethods
  def new_method
    "do some things"
  end
end


obj.extend ObjSingletonMethods

puts obj.new_method # => do some things

现在,如果您需要向该对象添加更多方法,您只需要在模块中实现这些方法即可。

答案 4 :(得分:1)

@media all and (max-aspect-ratio: 100/68){
   ...
   table#main td#mainLeft table#logoMoto{
     width: 30vw;
     height: 66vw;
     font-family: Arial, Helvetica, sans-serif;   
-->  font-size: 1.98vw;  // was font-size: 2vw;
     vertical-align: top; 
   }
   ...
}

语法class Some end obj = Some.new class << obj def hello puts 'hello' end end obj.hello obj2 = Some.new obj2.hello # error 意味着我们正在为对象打开类的定义。您可能知道我们可以使用如下语法定义Ruby类方法:

class << obj

然后我们可以使用这样的方法:

class Math

    class << self 

        def cos(x)
            ...
        end 

        def sin(x)
            ...
        end 
    end 
end 

在Ruby中,一切都是对象 - 甚至是类。 Math.cos(1) 此处是self本身的对象(您可以使用Math class访问该对象)。所以语法Math.class意味着我们正在为class << self打开课程。是的,这意味着Math class object也有类(Math.class.class)。

答案 5 :(得分:1)

有几种语法可以实现这一点,它们都与单例类有关:

  1. 您可以使用class <<惯用法打开单例类定义:

    obj = Object.new
    class << obj
      def my_new_method
         ...
      end
    end
    
  2. 或者您可以在obj:

    上使用define_singleton_method
    obj = Object.new
    obj.define_sigleton_method(:my_new_method) do
         ...
    end
    
  3. 您也可以使用单身类中的define_method

    obj = Object.new
    obj.singleton_class.define_method(:my_new_method) do
         ...
    end
    
  4. 或者您可以直接使用def

    obj = Object.new
    def obj.my_new_method
         ...
    end
    
  5. 注意例3,我认为单例类的概念在那一个上变得更加清晰。这两个例子之间存在差异:

        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
    

    这是因为每个对象都有自己的单例类:

        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)
    

答案 6 :(得分:1)

使用instance_eval

obj = SomeObject.new

obj.instance_eval do
  def new_method
    puts 'do something new'
  end
end

obj.new_method 
> "do something new"

答案 7 :(得分:0)

使用Mixin的另一种方式

obj = SomeObject.new
class << obj
  include AnotherModule
end

这包括从AnotherModule到当前对象的所有方法。