给出以下代码:
class Parent
CONSTANT = "Parent"
def self.do_the_thing
puts CONSTANT
puts self::CONSTANT
end
end
class Child < Parent
CONSTANT = "Child"
end
以下方法调用:
puts Parent.do_the_thing
# Parent
# Parent
puts Child.do_the_thing
# Parent
# Child
为什么Child.do_the_thing
不打印“儿童”两次?
答案 0 :(得分:3)
当您在do_the_thing
课程上致电Child
方法时,self
为Child
,因此self::CONSTANT
为Child::CONSTANT
('儿童')
当您在do_the_thing
课程上调用Parent
方法时,self
为Parent
,因此self::CONSTANT
为Parent::CONSTANT
('家长')
但是当你只调用CONSTANT
时,Ruby首先尝试在do_the_thing
方法所在的位置找到这个常量,对于这两种情况都是Parent
类。
答案 1 :(得分:3)
常量查找算法可以简化为:
因此,它首先尝试在最接近的词法封闭模块/类定义中找到常量,然后在该模块定义的词法封闭模块定义中查找,依此类推。如果它在那里找不到常数,那么然后 它会查看继承链。
我不认为matz曾经为这种算法提供了正式的理由,但是这种算法类似于Newspeak中的方法解析算法,而Gilad Bracha提供了以下理由:如果你编写方法,在词汇封闭的上下文中,你有一个就在你面前,如果它从系统的一个完全不同的部分中获取了一些其他值,那就太令人惊讶了。
转换为您的示例:CONSTANT
赋值直接位于方法定义的上方,如果该方法的作者没有获取正确分配的值,那么该方法的作者会感到惊讶在他面前。
在self::CONSTANT
案例中,您通过使用::
范围解析运算符明确指定查找的起点来跳过词汇查找部分。
注意:遗憾的是,常量查找实际上并非 。可悲的是,我不知道对它有任何好的描述。在她着名的"Three Implicit Contexts"文章中,yugui写道她没时间了,并会在后来的文章中解释不断查找,但不幸的是,她从未这样做过。