当你在调用某一个方法的时候,Ruby会完成下面的步骤:
self
的伪变量; 要理解Ruby的方法查找,你需要了解下面两个概念:接受者(receiver)和祖先链(ancestors chain)。接受者就是方法的调用者。例如,对调用an_object.display()
来说,an_object
就是接受者。而关于祖先链,请考察任何一个Ruby类的内部。想象一下从一个类移动到其父类,然后再移动到父类的父类,直到到达Object
类(默认的父类),然后继续移动,最终到达BasicObject
类(Ruby层级模型中的根)。你遍历这些类所走过的路径就是“祖先链”(祖先链中也包括模块)。
因此,为了查找方法,Ruby首先进入receiver所属的类,并以此为起始,沿着祖先链不断前进,直到找到目标方法。这种行为也被称作“向右一步,再向上(one step to the right, then up)”规则:向右一步,进入reciver所属的类,然后再向上查找祖先链,直到找到目标方法。(译者注:如果遍历完祖先链也没有找到方法的话,会调用method_missing
方法,如果这个方法没有被定义,则抛出NoMethodError
)当你在一个类中包含一个模块时,Ruby创建了一个匿名类来封装这个模块,并将这个匿名类插入到祖先链中,也在这个类的上方。
下面的代码演示了一次方法查找:
class A
def foo
end
end
class B < A
def bar
# bar method in B
end
end
class C < B
def bar
# bar method in C
# overwriting superclass' method
end
end
obj = C.new
obj.bar #=> in C class
obj.foo #=> not in C class
#=> then go to C's superclass B
#=> not in B class
#=> then go to B's superclass A
#=> execute it
self
是一个很特殊的变量,它总是指向当前对象(current object);self
被认为是默认的receiver。也就是说,你如果没有明确指出receiver,那么系统将把self
当做receiver;self
(当前对象)中查找的。也就是说,如果我使用@var
,那么Ruby就会在self
所指向的对象中去寻找此实例变量。需要注意的是,实例变量并不是由类定义的,它们也和子类以及继承机制无关。因此,当我们在调用一个明确指出receiver的方法时,Ruby会按照下面的步骤执行:
obj.do_method(param)
self
指向obj
;self
所属的类中查找do_method(param)
方法(方法是存放在类中,而不是实例中!);do_method(param)
;