2010-11-17 51 views
2

嘿家伙。 我如何知道在我的超类中覆盖子类的方法? 我有这样的:如何发现Ruby/Rails中被覆盖的方法?

 

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 

self.inherited的方法当加载测试的一个子类调用。所以我在child中获得了这个子类的引用,但是我不知道如何获得被这个子类覆盖的方法。

任何想法?

-

阿尔森建议使用self.method_added(名称),而不是self.inherited(孩子),但这种方法只能检测实例的方法,我想赶上类方法。有没有人知道另一种方法,但类方法做同样的事情? 在最后一种情况下,我会考虑使用单例并将所有这些类方法转换为实例方法,然后解决问题。

+0

澄清:你是否试图从'Test'调用'Child'方法? – 2010-11-17 12:58:22

+0

是的。我想知道孩子被忽视的方法。它们都是类方法,而child变量是对类Child的引用。 – 2010-11-17 13:38:34

+0

最简单的方法如何:“'Child.methods(false)&Test.methods(false)'”?问题是:你想什么时候打电话? '继承'被称为过早。 – Arsen7 2010-11-17 15:48:04

回答

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 

这只是问题的第一部分,因为您需要知道哪个类定义了方法(它将是自己的)以及方法是新的还是重写的。根据您的需要

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 
+0

这正是我需要的!非常感谢Arsen7!不幸的是我没有足够的声望(15)在这里投票给你...... =/ – 2010-11-18 13:40:08

+1

没关系!我很高兴我可以帮忙;) – Arsen7 2010-11-22 14:05:53

0

也许第一步解决方案:

通过调用child.instance_method(:bar)(如果孩子是指类)或child.method(:bar)(如果它指的是儿童的一个实例),你可以得到一个UnboundMethodMethod对象,表示你的方法:

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

不幸的是,a == b评估为假,虽然都指向同一个方法。

+0

我的错误。我忘了放“自我”。在所有方法定义之前。他们都是一流的方法。所以,我尝试了你所说的(使用child.method(:bar)和child.method(:foo)),并且都是在没有UnboundMethod的情况下执行的。我想它没有错误去foo方法,因为他使用超类方法。 – 2010-11-17 13:34:31

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

变化:与此代码实验。

+0

谢谢塔斯,但正如我之前所说,我试图捕捉类方法而不是实例方法。阿森斯找到了解决这个问题的方法。 – 2010-11-18 13:41:13

+0

's/instance_method/method',你很好走。 – Reactormonk 2010-11-19 13:23:05