是否可以使用块定义Ruby单例方法?

时间:2023-01-15 18:47:11

So, I want to define a singleton method for an object, but I want to do it using a closure.

所以,我想为一个对象定义一个单例方法,但我想用一个闭包来做。

For example,

例如,

def define_say(obj, msg)
  def obj.say
    puts msg
  end
end

o = Object.new
define_say o, "hello world!"
o.say

This doesn't work because defining a singleton method via "def" is not a closure, so I get an exception that "msg" is an undefined variable or method.

这不起作用,因为通过“def”定义单例方法不是闭包,所以我得到一个例外,“msg”是一个未定义的变量或方法。

What I would like to do is something like using the "define_method" method in the Module class, but as far as I can tell, this can only be used to define a method on a class... but I want a Singleton Method...

我想做的就是在Module类中使用“define_method”方法,但据我所知,这只能用于在类上定义方法......但我想要一个Singleton方法。 ..

So, I would love to write it something like this:

所以,我想写这样的东西:

def define_say(obj, msg)
  obj.define_singleton_method(:say) {
    puts msg
  }
end

Does anyone know how I can achieve this without having to create a method to store a Proc and then use the Proc within a singleton method? (basically, I want a clean, non-hacky way of doing this)

有没有人知道如何实现这一点,而无需创建一个存储Proc的方法,然后在单例方法中使用Proc? (基本上,我想要一个干净,非hacky这样做的方式)

2 个解决方案

#1


8  

Here's an answer which does what you're looking for

这是一个答案,可以满足您的需求

def define_say(obj, msg)
  # Get a handle to the singleton class of obj
  metaclass = class << obj; self; end 

  # add the method using define_method instead of def x.say so we can use a closure
  metaclass.send :define_method, :say do
    puts msg
  end
end

Usage (paste from IRB)

用法(从IRB粘贴)

>> s = "my string"
=> "my string"
>> define_say(s, "I am S")
=> #<Proc:0xb6ed55b0@(irb):11>
>> s.say
I am S
=> nil

For more info (and a little library which makes it less messy) read this:

有关更多信息(以及一个使其不那么混乱的小库)请阅读:

http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html

http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html

As an aside, If you're a ruby programmer, and you HAVEN'T read that, go do it now~!

顺便说一句,如果你是一个红宝石程序员,而你还没有读过,那就去吧〜!

#2


14  

Object#define_singleton_method was added to ruby-1.9.2 by the way:

对象#define_singleton_method顺便添加到ruby-1.9.2:

def define_say(obj, msg)
  obj.define_singleton_method(:say) do
    puts msg
  end
end

#1


8  

Here's an answer which does what you're looking for

这是一个答案,可以满足您的需求

def define_say(obj, msg)
  # Get a handle to the singleton class of obj
  metaclass = class << obj; self; end 

  # add the method using define_method instead of def x.say so we can use a closure
  metaclass.send :define_method, :say do
    puts msg
  end
end

Usage (paste from IRB)

用法(从IRB粘贴)

>> s = "my string"
=> "my string"
>> define_say(s, "I am S")
=> #<Proc:0xb6ed55b0@(irb):11>
>> s.say
I am S
=> nil

For more info (and a little library which makes it less messy) read this:

有关更多信息(以及一个使其不那么混乱的小库)请阅读:

http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html

http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html

As an aside, If you're a ruby programmer, and you HAVEN'T read that, go do it now~!

顺便说一句,如果你是一个红宝石程序员,而你还没有读过,那就去吧〜!

#2


14  

Object#define_singleton_method was added to ruby-1.9.2 by the way:

对象#define_singleton_method顺便添加到ruby-1.9.2:

def define_say(obj, msg)
  obj.define_singleton_method(:say) do
    puts msg
  end
end