2012-01-01 117 views
5

受此article的启发,我在玩Ruby方法调用层次结构并注意到一些奇怪的事情。Ruby方法调用层次结构

考虑:

class B 
    def foo 
    "- Instance method defined by B" 
    end 

    def method_missing(method) 
    puts "- method_missing (#{method}) on b. Redirecting to b.foo\n" 
    foo 
    end 
end 

b = B.new 

def b.foo 
    "- Method defined directly on an instance of B\n" + super 
end 

def b.method_missing(method) 
    "- method_missing (#{method}) on b. Calling super\n" + super 
end 

puts "Calling 'bar' on b of type #{b.class}:" 
puts b.bar 

运行它给:

Calling 'bar' on b of type B: 
- method_missing (bar) on b. Redeirecting to b.foo 
- method_missing (bar) on b. Calling super 
- Method defined directly on an instance of B 
- instance method defined by B 

我的问题是:

由于我打电话b.bar(在对象上),怎么来的类的实例方法在调用objet的实例方法之前调用?

我本来期望b.method_missing(method)首先被调用,然后类的实例method_missing(method)(因为我调用超?但超是类层次结构...),其中不重定向从barfoo。 另外,为什么在重定向到foo之后,实例的missing_method被调用?我们被告知我们正在重定向...

我想我不明白Ruby如何允许在一个类的实例(新对我)中定义实例方法的概念,而不是将其定义为类的实例方法(经典语言)。

我希望这个问题是有道理的,也许我的头仍然是从昨晚纺...

+1

我的返回值一起输出在b.method_missing字符串看到的第一线删除不相关的代码,使问题更加明显。提供一个* minimal *问题的例子通常是一个好主意。 – 2012-01-02 00:11:21

回答

4

的问题是,你的输出并不反映执行的实际顺序。让我们来看看输出:

method_missing (bar) on b. Redeirecting to b.foo 
method_missing (bar) on b. Calling super 

乍一看,这给人的印象是B#method_missing是单身方法b.method_missing这引起了你所描述的两个问题之前调用。实际上,b.method_missing被正确地称为第一个。如果你看一下声明puts b.bar如何评价这得到明确:

  1. b没有方法bar,所以b.method_missing被调用带有字符串'bar'作为参数。
  2. b.method_missing依次通过使用super关键字调用方法B#method_missing
  3. B#method_missing使用puts到输出上述
  4. 单身方法b.foo
  5. 最外puts执行被调用,这与b.foo
+2

+1;打败了我。 – 2012-01-02 00:09:17

+0

Niklas,谢谢澄清(并删除不相关的代码)。谢谢您的回答! – dynex 2012-01-02 06:01:03

+0

在调试器中运行它当然可以澄清它。我应该做到这一点 - 对不起,我感谢你的耐心。 – dynex 2012-01-02 06:22:22