如何在Ruby / Rails中发现重写的方法?

时间:2010-11-17 12:43:37

标签: ruby-on-rails ruby inheritance override

嘿伙计们。 我怎么知道子类在我的超类中覆盖的方法? 我有这个:


class Test
  def self.inherited(child)
    # child.overrided_methods???
  end

  def self.foo
  end

  def self.bar
  end
end

def Child < Test
  def self.bar
    puts "bar"
  end
end

加载Test的子类时调用self.inherited方法。所以我在child中引用了这个子类,但我不知道如何获得被这个子类重写的方法。

有什么想法吗?

-

Arsen建议使用self.method_added(name)而不是self.inherited(child),但是这个方法只捕获实例方法,我想捕获类方法。有没有人知道用类方法做同样事情的另一种方法? 在最后一种情况下,我会考虑使用单例并将所有这些类方法转换为实例方法,然后问题就解决了。

3 个答案:

答案 0 :(得分:2)

例如,方法可以覆盖Object::method_added(name)方法,类似于您使用的“继承”方法:

class test
  def self.method_added(name)
    puts "method_added(#{name.inspect})"
    super
  end
end

irb(main):002:0> class Child < Test; def foo; end; end
method_added(:foo)
=> nil

然后,您可以将收到的名称与方法列表进行比较:

Test.instance_methods.include?(name.to_s)

使用类方法这种方法不起作用(即使你做了class << self魔法之类的事情),但是一个有帮助的人知道答案:http://www.ruby-forum.com/topic/120416

class Test
  def self.singleton_method_added(name)
    puts "Class method added #{name.inspect}"
  end
end

这只是问题的第一部分,因为您需要知道哪个类定义了方法(它将是self)以及该方法是新方法还是重写方法。试用这段代码:

class Test
  def self.singleton_method_added(name)
    if self == Test
      puts "My own class method added: #{self.name}.#{name.inspect}"
    elsif Test.methods(false).include?(name.to_s)
      puts "Class method overriden: #{self.name}.#{name.inspect}"
    elsif Test.methods(true).include?(name.to_s)
      puts "My parent's class method overriden: #{self.name}.#{name.inspect}"
    else
      puts "New class method added: #{self.name}.#{name.inspect}"
    end
  end
end

答案 1 :(得分:0)

也许是解决方案的第一步:

通过调用child.instance_method(:bar)(如果孩子引用该类)或child.method(:bar)(如果它引用了Child的实例),您可以获得UnboundMethodMethod个对象代表你的方法:

a = Test.instance_method(:foo)
b = Child.instance_method(:foo)

不幸的是,a == b的计算结果为false,尽管两者都指的是相同的方法。

答案 2 :(得分:0)

def overridden_methods
  klass = self.class
  klass.instance_methods.select {|m| klass.instance_method(m).owner == klass}
end

根据您的需要进行更改。