ruby 将方法添加到示例化对象

ztigrdn8  于 12个月前  发布在  Ruby
关注(0)|答案(9)|浏览(132)
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


也可以,但是在一个方法中包含一个方法看起来很可怕。问题是,有没有其他方法可以添加这样的方法?

nwlls2ji

nwlls2ji1#

在ruby 1.9+中,有一种更好的方法可以使用define_singleton_method,如下所示:

obj = SomeObject.new

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

字符串

holgip5t

holgip5t2#

使用Mixin。

module AdditionalMethods
  def new_method
    "do some things"
  end
end

obj = SomeObject.new
obj.extend(AdditionalMethods)

puts obj.new_method
> "do some things"

字符串

b5buobof

b5buobof3#

有几种方法可以实现这一点,它们都与单例类有关:
1.你可以使用class <<习惯用法来打开单例类定义:

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

字符串
1.或者你可以在obj上使用define_singleton_method

obj = Object.new
 obj.define_singleton_method(:my_new_method) do
      ...
 end


1.你也可以在singleton类中使用define_method

obj = Object.new
 obj.singleton_class.define_method(:my_new_method) do
      ...
 end


1.也可以直接使用def

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


注意例子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)

wlwcrazw

wlwcrazw4#

只是一个有趣的点要注意:
如果你去了:

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被定义在示例的特征类上。
与你的问题没有直接关系,但有点有趣;)

tjvv9vkg

tjvv9vkg5#

你可以使用模块。

module ObjSingletonMethods
  def new_method
    "do some things"
  end
end

obj.extend ObjSingletonMethods

puts obj.new_method # => do some things

字符串
现在,如果你需要向该对象添加更多的方法,你只需要在模块中实现这些方法,就完成了。

xghobddn

xghobddn6#

使用instance_eval

obj = SomeObject.new

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

obj.new_method 
> "do something new"

字符串

nxowjjhe

nxowjjhe7#

class Some
end 

obj = Some.new

class << obj
  def hello 
    puts 'hello'
  end 
end 

obj.hello

obj2 = Some.new
obj2.hello # error

字符串
class << obj意味着我们正在为一个对象打开类的定义。正如你可能知道的,我们可以使用这样的语法来定义Ruby类方法:

class Math

    class << self 

        def cos(x)
            ...
        end 

        def sin(x)
            ...
        end 
    end 
end


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

Math.cos(1)


在Ruby中,所有东西都是对象--甚至类也是。self在这里是Math class本身的对象(你可以用Math.class访问那个对象)。所以语法class << self意味着我们为Math class object打开了类。是的,它意味着Math class也有类(Math.class.class)。

dwthyt8l

dwthyt8l8#

另一种使用Mixin的方法

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

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

jvidinwx

jvidinwx9#

使用define_singleton_method是在稍后尝试转储对象时出现错误singleton can't be dumped的原因。
看起来,为示例化的对象设置一个新属性就足够满足我的需要了。

obj = Object.new

obj.class.module_eval { attr_accessor :new_method }
obj.new_method = "do some things"

puts obj.new_method
> "do some things"

字符串
它部分地回答了这个问题,因为设置为obj的函数是由attr_accessor设置的(而不是任意设置的)。但是,当属性足够时,它仍然是一个解决方案。

相关问题