父类的方法访问子类的常量时的Quirk

时间:2017-03-14 07:24:47

标签: ruby oop

给出以下代码:

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不打印“儿童”两次?

2 个答案:

答案 0 :(得分:3)

当您在do_the_thing课程上致电Child方法时,selfChild,因此self::CONSTANTChild::CONSTANT('儿童')

当您在do_the_thing课程上调用Parent方法时,selfParent,因此self::CONSTANTParent::CONSTANT('家长')

但是当你只调用CONSTANT时,Ruby首先尝试在do_the_thing方法所在的位置找到这个常量,对于这两种情况都是Parent类。

答案 1 :(得分:3)

常量查找算法可以简化为:

  1. 词汇&#34;向外&#34;
  2. &#34;向上&#34;通过继承
  3. 因此,它首先尝试在最接近的词法封闭模块/类定义中找到常量,然后在该模块定义的词法封闭模块定义中查找,依此类推。如果它在那里找不到常数,那么然后 它会查看继承链。

    我不认为matz曾经为这种算法提供了正式的理由,但是这种算法类似于Newspeak中的方法解析算法,而Gilad Bracha提供了以下理由:如果你编写方法,在词汇封闭的上下文中,你有一个就在你面前,如果它从系统的一个完全不同的部分中获取了一些其他值,那就太令人惊讶了。

    转换为您的示例:CONSTANT赋值直接位于方法定义的上方,如果该方法的作者没有获取正确分配的值,那么该方法的作者会感到惊讶在他面前。

    self::CONSTANT案例中,您通过使用::范围解析运算符明确指定查找的起点来跳过词汇查找部分。

    注意:遗憾的是,常量查找实际上并非 。可悲的是,我不知道对它有任何好的描述。在她着名的"Three Implicit Contexts"文章中,yugui写道她没时间了,并会在后来的文章中解释不断查找,但不幸的是,她从未这样做过。