如何调用super来动态定义Ruby中子类中的方法?

时间:2014-04-12 22:15:15

标签: ruby exception metaprogramming

我有这个元编程方案,触及Ruby的一些更精细的功能,我不太确定如何解决。

每个人都可以轻松编写下面的示例来执行它应该做的事情,但我需要在超类和派生子类中动态定义方法。

在示例中,基类具有动态定义的方法:foo和cource,它暴露给子类B. 但是,当我在子类B的实例上调用:foo时,我在动态定义的方法中检测到,我似乎无法将它从B类实例传递到A类实例,而cource就是我想要的

wierd ruby​​的类别定义了子类中的方法,但无论如何,这就是我想要解决的问题。

任何线索?

class A
  def self.some_method method,*_params
    puts "#{name}: defining #{method}"
    define_method method do |*args|
      puts "#{self.class.name}: called #{method}"
      super *args unless self.class.instance_methods(false).include?(method)
    end
  end
end

class B < A
end

A.some_method :foo

B.new.foo

输出

A: defining foo
B: called foo
NoMethodError: super: no superclass method `foo' for #<B:0x007f9eab85bfa0>

2 个答案:

答案 0 :(得分:3)

我认为你的逻辑存在缺陷。

您可以为超类A定义动态方法。调用B.new.fooB中找不到任何方法,因此它会继承继承行。它在foo中找到了A方法,因此它使用了该方法  这意味着

super *args unless self.class.instance_methods(false).include?(method)
部分根本不需要。

我看到它的方式,经典的方法继承就是你所需要的!

答案 1 :(得分:0)

确实存在缺陷的逻辑。当然需要访问具有定义方法的类,而超级无法帮助你。

以下是解决问题的方法:

class A
  def self.some_method method,*_params
    puts "#{name}: defining #{method}"
    define_method method do |*args|
      puts "#{self.class.name}: called #{method}"

      klass = self.class
      klass = klass.superclass while !klass.instance_methods(false).include?(method)

      # klass is now where the instance method is defined
      # and you can now access its class variables etc.
      puts "#{klass.name}: has method #{method}"
    end
  end
end

class B < A
end

A.some_method :foo

B.new.foo

输出

A: defining foo
B: called foo
A: has method foo