我希望在特定对象中添加单身方法。我希望,当对象上首先调用实例方法时,它可以进行一些工作,然后为同名对象创建单例方法(包含工作)。在上述对象的所有后续调用中,单例方法将遮蔽实例方法,并将被调用。

我知道如何创建单身方法,我的问题是我想创建的单例方法来调用lambda(l 在这种情况下)。 DEF不会创建关闭,因此当该方法随后调用时,我无法引用变量L(下面的代码)(代码)(代码)(l.call() 在此示例中进行了评论)我希望知道如何在特定对象上创建单例方法时如何创建关闭。任何帮助,将不胜感激。谢谢你。

class Thing
end

t = Thing.new
t2 = Thing.new

Thing.instance_eval() do
  def speak
    puts "I speak for all Things, I am a class method"
  end
end

Thing.class_eval() do
  def speak
    puts "This is the instance method referenced by the Thing object #{self}"
    r = "something I wish to hold on to, maybe expensive to calculate"
    l = lambda {puts r}
    instance_eval() do
      def speak()
        puts "This is the singleton method in the Thing object #{self}"
        #l.call() # I want this to work! How?
      end
    end
  end
end

Thing.speak()
t.speak()
t2.speak()
t.speak()
t2.speak()

运行时给出以下结果:(我将'<'更改为'#',所以它们出现在html中)

我说所有的话,我是班级方法

这是事物对象#thing引用的实例方法:0x1d204>

这是事物对象#thing引用的实例方法:0x1d1dc>

这是事物对象#thing中的单例方法:0x1d204>

这是事物对象#thing中的单例方法:0x1d1dc>

有帮助吗?

解决方案

您可以使用块来定义一种方法 define_method.

例子:

class Object
  def eigenclass
    class <<self; self end
  end
end

a = "Hello"
other_word = "World"
a.eigenclass.class_eval do
  define_method(:cliche) {"#{self} #{other_word}"}
end
a.cliche # => "Hello World"
"Goodbye".cliche # => NoMethodError: undefined method `cliche' for "Goodbye":String

这是一个实现 define_singleton_method 方法:

class Object
  def define_singleton_method(name, &block)
    eigenclass = class<<self; self end
    eigenclass.class_eval {define_method name, block}
  end
end

其他提示

既然1.9都可以使用Define_singleton_method:

jruby --1.9 -S irb
irb(main):019:0> fn = -> { length * 10 }
=> #<Proc:0x77cb8e0f@(irb):19 (lambda)>
irb(main):020:0> s.define_singleton_method :length_times_ten, fn
=> #<Proc:0x77cb8e0f@(irb):19 (lambda)>
irb(main):021:0> s
=> "a string"
irb(main):022:0> s.length_times_ten
=> 80

好吧,一种方法是将其包装到实例变量中:

(仅供参考 class Thing 重新开放 Thing (比使用短一点 #class_eval, ,你不需要 #instance_eval 从方法内定义方法)。

class Thing
  def speak
    puts "This is the instance method referenced by the Thing object #{self}"
    r = "something I wish to hold on to, maybe expensive to calculate"
    @l = lambda {puts r}
    instance_eval do 
      def speak()
        puts "This is the singleton method in the Thing object #{self}"
        @l[]
      end
    end
  end
end

这将重新定义 #speak, ,但仅用于那个实例 Thing. 。其他实例 Thing 仍将具有原始定义。

正如查克(Chuck)指出的那样,另一种选择是使用与实例关联的Singleton类(又名Metaclass,aka eigenclass)。 Singleton类是存储与对象关联的所有Singleton方法的对象。您可以通过使用Funny来获得Singleton类评估的上下文 class <<object ; ... ; end 语法(类似于由 #class_eval 按照正常类)。

class Thing
  def speak
    puts "This is the instance method referenced by the Thing object #{self}"
    r = "something I wish to hold on to, maybe expensive to calculate"
    singleton_class = class <<self # open singleton class context for current instance
      # in this context, self now refers to the singleton class itself
      self
    end
    l = lambda {puts r}
    singleton_class.class_eval do
      # since we used #class_eval, local variables are still in scope
      define_method(:speak) do 
        puts "This is the singleton method in the Thing object #{self}"
        # since we used #define_method, local variables are still in scope
        l[]
      end
    end
  end
end
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top