Given the following code:
class Parent
  CONSTANT = "Parent"
  def self.do_the_thing
    puts CONSTANT
    puts self::CONSTANT
  end
end
class Child < Parent
  CONSTANT = "Child"
end
And the following method calls:
puts Parent.do_the_thing
# Parent
# Parent
puts Child.do_the_thing
# Parent
# Child
Why doesn't Child.do_the_thing print "Child" twice?
The constant lookup algorithm may be simplified to:
So, it first tries to find the constant in the closest lexically enclosing module / class definition, then the lexically enclosing module definition of that module definition, and so on. If it cannot find the constant there, then and only then does it look at the inheritance chain.
I don't think that matz has ever provided a formal justification for this algorithm, but this algorithm is similar to the method resolution algorithm in Newspeak, and Gilad Bracha provided the following justification: if you write a method, and you have a value right in front of you in the lexically enclosing context, it would be surprising, if it picked up some other value from a completely different part of the system.
Translated to your example: the CONSTANT assignment is literally directly above the method definition, it would be surprising to the author of that method, if it didn't pick up the value that is being assigned right in front of his eyes.
In the self::CONSTANT case, you skip the lexical lookup part by specifying the start point for the lookup explicitly using the :: scope resolution operator.
Note: unfortunately, constant lookup is not actually that simple. Sadly, I don't know of any good description of it. In her famous "Three Implicit Contexts" article, yugui wrote she ran out of time and would explain constant lookup in a later article, but unfortunately, she never did.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With