简体   繁体   English

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

[英]How to call super on dynamicly defined methods in sub-classes in Ruby?

I have this metaprogramming scenario that touches some of the finer features of Ruby that I am not quite sure how to solve. 我有一个元编程方案,它涉及到我不确定如何解决的Ruby的一些较优功能。

Everyone can easilly program the example below to do what its supposed to do, but I need to define methods dynamicly in both super-classes and derived sub-classes. 每个人都可以轻松编写以下示例的程序来执行其应做的事情,但是我需要在超类和派生子类中动态定义方法。

In the example the base class has a dynamicly defined method :foo and of cource it is exposed to the sub-class B. However, when I call :foo on a instance of the sub-class B, which I detect in the dynamicly defined method I cant seem to pass it down from the B class instance down to the A class instance that of cource is what I want. 在该示例中,基类具有动态定义的方法:foo,当然,它公开给子类B。但是,当我在子类B的实例上调用:foo时,我在动态定义的方法中检测到我似乎无法将方法从B类实例传递到A类实例,这就是我想要的。

Sort of wierd ruby defines the method in the sub-class too like that, but anyways, thats what I am trying to work around. 有点像红宝石一样在子类中定义方法,但是无论如何,这就是我要解决的问题。

Any clues? 有什么线索吗?

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

Output 输出量

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

I think there is a flaw in your logic. 我认为您的逻辑存在缺陷。

You define the dynamic method to the superclass A . 您可以为超类A定义动态方法。 Calling B.new.foo find no method in B so it goes up the inheritance line. 调用B.new.fooB找不到任何方法,因此它继承了继承行。 It finds the foo method in A so it uses that one. 它在A找到foo方法,因此使用该方法。
That means that the 这意味着

super *args unless self.class.instance_methods(false).include?(method)
part is not needed at all. 根本不需要。

The way I see it, classic method inheritance is all you need! 按照我的看法,经典方法继承就是您所需要的!

The logic where indeed flawed. 逻辑确实存在缺陷。 The need where of course to access the class that has the method defined, and super can't help you there. 当然需要在何处访问已定义方法的类,而super并不能帮助您。

Following is the solution to the problem: 以下是该问题的解决方案:

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

Output 输出量

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM