动态定义实例方法中的方法

时间:2017-04-06 11:13:10

标签: ruby methods dynamic

我正在研究ruby中面向上下文的编程项目。我遇到了这个问题:

假设我有一个Klass类:

class Klass
    def my_method
        proceed
    end
end

我还在变量impl中存储了一个proc。 impl包含{ puts "it works!" }

从Klass以外的某个地方,我想在方法proceed中定义一个名为my_method的方法。因此,如果调用Klass.new.my_method,我会得到结果"it works"

所以最后的结果应该是这样的:

class Klass
    def my_method
        def proceed
            puts "it works!"
        end
        proceed
    end
end

或者如果您有任何其他想法让proceed my_method内的proceed调用,那也很好。但是另一种方法my_method_2(比方说my_method)与proceed不同。 实际上,my_method的{​​{1}}代表my_method的旧版本。 proceed的{​​{1}}代表my_method_2的旧版本。

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

免责声明: 你做错了!

必须更健壮,优雅和红宝石的方式来实现你想要的。如果您仍想滥用元编程,请转到:

class Klass
  def self.proceeds
    @proceeds ||= {}
  end

  def def_proceed
    self.class.proceeds[caller.first[/`.*?'/]] = Proc.new
  end

  def proceed *args
    self.class.proceeds[caller.first[/`.*?'/]].(*args)
  end

  def m_1
    def_proceed { puts 1 }
    proceed
  end

  def m_2
    def_proceed { puts 2 }
    proceed
  end
end

inst = Klass.new

inst.m_1
#⇒ 1
inst.m_2
#⇒ 2

您实际需要的是Module#prepend并从那里致电super

答案 1 :(得分:0)

这样做的一种方法是构造一个哈希,其键是调用proceed的方法的名称,其值是proc,表示调用它的每个方法的proceed的实现。

class Klass
  singleton_class.send(:attr_reader, :proceeds)
  @proceeds = {}
  def my_method1(*args)
    proceed(__method__,*args)
  end
  def my_method2(*args)
    proceed(__method__,*args)
  end
  def proceed(m, *args)
    self.class.proceeds[m].call(*args)
  end
end

def define_proceed(m, &block)
  Klass.proceeds[m] = Proc.new &block
end

define_proceed(:my_method1) { |*arr| arr.sum }
define_proceed(:my_method2) { |a,b| "%s-%s" % [a,b] }

k = Klass.new
k.my_method1(1,2,3)        #=> 6
k.my_method2("cat", "dog") #=> "cat-dog"