受到这个article的启发,我正在玩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)
(因为我调用super?但是super是类层次结构...),它从{{重定向1}}到bar
。
另外,在被重定向到foo
之后,如何调用实例的missing_method?我们刚被告知我们正被重定向......
我认为我不理解Ruby如何允许在类的实例上定义实例方法(对我来说是新的),而不是将其定义为类的实例方法(经典语言)
我希望这个问题有道理,也许我的头脑仍在从昨晚开始......
答案 0 :(得分: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
的评估方式,这一点就很明确了:
b
没有方法bar
,因此使用字符串b.method_missing
作为参数调用'bar'
。b.method_missing
依次使用B#method_missing
关键字调用方法super
。B#method_missing
使用puts
输出上面的第一行b.foo
被称为puts
,输出b.method_missing
中的字符串以及b.foo
的返回值