代码之家  ›  专栏  ›  技术社区  ›  hoffm

为什么Ruby找不到调用方类中定义的常量?

  •  1
  • hoffm  · 技术社区  · 7 年前

    考虑以下代码:

    class MyClass
      def foo_via_method
        foo_method
      end
    
      def foo_via_constant
        FOO_CONSTANT
      end
    end
    
    class SubClass < MyClass
      FOO_CONSTANT = "foo"
    
      def foo_method
        FOO_CONSTANT
      end
    end
    

    sub_class_instance = SubClass.new
    
    ### THIS WORKS ###
    sub_class_instance.foo_via_method
    # => "foo"
    
    ### THIS DOESN'T ###
    sub_class_instance.foo_via_constant
    # NameError: uninitialized constant MyClass::FOO_CONSTANT
    

    引用子类中方法的版本返回所需的值,但引用子类中常量的版本抛出错误。所以问题是:为什么使用方法的版本可以工作,但使用常量的版本失败了?

    1 回复  |  直到 7 年前
        1
  •  2
  •   hoffm    7 年前

    这是我在实际生产代码中遇到的一个难题。我写了一份详细的解释,解释了 this blog post .

    这是TLDR:Ruby使用了比方法更复杂的算法来解析常量。常量查找例程的一个阶段涉及通过超类链查找定义。这个阶段看起来很像方法查找例程,加深了为什么方法和常量在问题中所示的方式不同的谜团。

    解释是这两个超类链例程在它们的位置不同 开始 ,即哪个类是链的根。

    self 的类,其中 自己 是原始方法调用的接收器。在本例中, sub_class_instance 是接收器和 SubClass 是查找开始的位置。 子类 机具 foo_method

    对于常量,Ruby不引用接收器,因为常量调用与接收器无关。相反,常量超类查找从在发生常量调用的词法范围中打开的类开始。在本例中,打开的类是 MyClass 这就是Ruby开始寻找Constant的地方,但一直没有找到它。