Ruby 将方法添加到实例化对象

Ruby 将方法添加到实例化对象,ruby,Ruby,这样行。但是,我需要在现有方法中执行相同的操作: obj = SomeObject.new def obj.new_method "do some things" end puts obj.new_method > "do some things" 也可以,但是在一个方法中有一个方法看起来非常可怕。问题是,有没有其他方法可以添加这种方法?使用Mixin def some_random_method def obj.new_method "do some things"

这样行。但是,我需要在现有方法中执行相同的操作:

obj = SomeObject.new

def obj.new_method
  "do some things"
end

puts obj.new_method
> "do some things"
也可以,但是在一个方法中有一个方法看起来非常可怕。问题是,有没有其他方法可以添加这种方法?

使用Mixin

def some_random_method
  def obj.new_method
    "do some things"
  end
end
您可以使用模块

module AdditionalMethods
  def new_method
    "do some things"
  end
end

obj = SomeObject.new
obj.extend(AdditionalMethods)

puts obj.new_method
> "do some things"

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

需要注意的一点是:

如果你去了:

module ObjSingletonMethods
  def new_method
    "do some things"
  end
end


obj.extend ObjSingletonMethods

puts obj.new_method # => do some things
然后,
my\u other\u方法
实际上将在对象的类上定义,尽管
my\u方法
的接收者是一个实例

但是,如果您(像您那样)去:

然后在实例的特征类上定义
my\u other\u方法


与您的问题不直接相关,但还是有点有趣;)

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

def my_method
    def self.my_other_method; end
end

在Ruby中,一切都是一个对象,甚至是类
self
这里有一个
Math class
本身的对象(您可以使用
Math.class
访问该对象)。因此语法
class有几种方法可以实现这一点,它们都与singleton类相关:

 obj = Object.new
 obj.define_singleton_method(:my_new_method) do
      ...
 end
    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

  • 您可以使用
    class使用
    instance\u eval

        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)
    

    使用Mixin的另一种方法

    obj = SomeObject.new
    
    obj.instance_eval do
      def new_method
        puts 'do something new'
      end
    end
    
    obj.new_method 
    > "do something new"
    
    obj=SomeObject.new
    
    类您确定第二段代码有效吗?因为我想它应该首先接受
    obj
    作为一个方法参数,在它上面定义一个单例方法。所以他的算法有时会把最新的答案放在最前面。很有趣。我以后会看得更远。如果我在这个
    do
    块中使用
    @field
    ,会发生什么?我会从当前类访问一个字段,还是它会使用
    obj
    的字段?还没有真正正确地测试过这一点,但据我所知,mixin和这种方法是不等价的。这可以访问外部值,而mixin不能。您好,有拼写错误。define_sigleton_方法,在2的代码中应该是define_singleton_方法。@fanjieqi已修复。谢谢
    Math.cos(1)
    
     obj = Object.new
     class << obj
       def my_new_method
          ...
       end
     end
    
     obj = Object.new
     obj.define_singleton_method(:my_new_method) do
          ...
     end
    
     obj = Object.new
     obj.singleton_class.define_method(:my_new_method) do
          ...
     end
    
     obj = Object.new
     def obj.my_new_method
          ...
     end
    
        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)
    
    obj = SomeObject.new
    
    obj.instance_eval do
      def new_method
        puts 'do something new'
      end
    end
    
    obj.new_method 
    > "do something new"
    
    obj = SomeObject.new
    class << obj
      include AnotherModule
    end