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

Is it possible to define a Ruby singleton method using a block?

提问人:Mike Stone 提问时间:9/26/2008 更新时间:5/28/2015 访问量:5926

问:

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

例如

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

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

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

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

所以,我很想把它写成这样:

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

有谁知道我如何实现这一点,而不必创建一个方法来存储一个 Proc,然后在一个单一的方法中使用 Proc?(基本上,我想要一种干净的、非黑客的方式来做到这一点)

Ruby 闭包 单例方法

评论


答:

8赞 Orion Edwards 9/26/2008 #1

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

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

用法(从IRB粘贴)

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

欲了解更多信息(以及一个使其不那么混乱的小库),请阅读以下内容:

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

顺便说一句,如果你是一个 ruby 程序员,而且你还没有读过,现在就去做吧~!

评论

0赞 Andrew Grimm 6/23/2011
我更改了链接,因为自从发布此答案以来_why AWOL。
14赞 asymmetric 6/23/2011 #2

顺便说一下,Object#define_singleton_method 被添加到 ruby-1.9.2 中:

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