如何在Ruby中为new创建一个未绑定的方法

时间:2013-05-31 00:13:05

标签: ruby-on-rails ruby metaprogramming function-pointers

我有这段代码:

class Note < Struct.new :value
  def to_s
    value.to_s
  end
  def self.use_new(arg)
    Note.new arg
  end
end

class Chord
  def initialize(arr)
    @arr = arr
  end

  def play
    @arr.join('-')
  end
end
new_method = Note.singleton_method(:use_new)
chords = %w{ G Bb Dd E }
c = Chord.new(chords.map(:new_method))
puts c.play

现在我知道我不必使用地图,我只需使用map {|n| Note.new n}

但我想知道如何做到这一点。以下说注意没有名为singleton_method的方法。当我尝试使用实例方法(在定义中没有self)时,它表示该方法不存在。请指教。

2 个答案:

答案 0 :(得分:2)

试试这个:

new_method = (class << Note; self; end).instance_method(:use_new)

这解决了主要问题,但还有其他问题。

答案 1 :(得分:2)

为什么要UnboundMethodUnboundMethod对你的理解并不多。特别是,你不能call它。您唯一能做的就是bind它是module的一个实例,以获得绑定Method。但是,在这种情况下,有问题的moduleNote的单例类,它只有一个实例,所以你只能bindNote。所以,您可能首先得到一个绑定的Method

new_method = Note.method(:use_new)
chords = %w{ G Bb Dd E }
c = Chord.new(chords.map(&new_method)) # BTW: you had a typo here
puts c.play

我也不明白你Note::use_new的目的是什么。它只是Note::new周围的无操作包装,因此它也可能是alias_method。或者,更好的是,只需删除它,它不会服务于任何目的:

new_method = Note.method(:new)
chords = %w{ G Bb Dd E }
c = Chord.new(chords.map(&new_method)) # BTW: you had a typo here
puts c.play

如果您想确保获取单件方法,您也可以使用singleton_method

new_method = Note.singleton_method(:use_new)
chords = %w{ G Bb Dd E }
c = Chord.new(chords.map(&new_method)) # BTW: you had a typo here
puts c.play

如果您确实坚持要UnboundMethod,那么您必须首先bind才能使用它,然后您必须从中获取它单身类,因为singleton_method返回Method而不是UnboundMethod

new_method = Note.singleton_class.instance_method(:use_new)
chords = %w{ G Bb Dd E }
c = Chord.new(chords.map(&new_method.bind(Note)))
puts c.play