【问题标题】:Quirk when parent's class method accesses the subclass's constants父类方法访问子类常量时的怪癖
【发布时间】:2017-03-14 07:24:47
【问题描述】:

给定以下代码:

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

【问题讨论】:

    标签: ruby oop


    【解决方案1】:

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

    1. 词汇上的“向外”
    2. 通过继承“向上”

    因此,它首先尝试在最接近的词法封闭模块/类定义中查找常量,然后是该模块定义的词法封闭模块定义,依此类推。如果它在那里找不到常量,然后只有在它会查看继承链。

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

    翻译为您的示例:CONSTANT 赋值实际上直接位于方法定义之上,如果该方法的作者没有拾取在他的前面分配的值,那会令该方法的作者感到惊讶眼睛。

    self::CONSTANT 的情况下,您可以通过使用:: 范围解析运算符显式指定查找的起点来跳过词法查找部分。

    注意:不幸的是,持续查找实际上不是那么简单。可悲的是,我不知道有什么好的描述。在她著名的"Three Implicit Contexts" 文章中,yugui 写道她没时间了,将在以后的文章中解释不断查找,但不幸的是,她从来没有这样做过。

    【讨论】:

      【解决方案2】:

      当您在 Child 类上调用 do_the_thing 方法时,selfChild,所以 self::CONSTANTChild::CONSTANT('Child')。

      当您在 Parent 类上调用 do_the_thing 方法时,selfParent,所以 self::CONSTANTParent::CONSTANT('Parent')。

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

      【讨论】:

        猜你喜欢
        • 2012-02-19
        • 2012-02-04
        • 2012-07-04
        • 2012-10-28
        • 2020-02-13
        • 2023-04-01
        • 1970-01-01
        • 2014-10-04
        • 1970-01-01
        相关资源
        最近更新 更多