I was plodding my way along The Path To Enlightenment, this morning (ruby koans), and I was rather stumped on the following:
class Animal
LEGS = 4
def legs_in_animal
LEGS
end
end
class MyAnimals
LEGS = 2
class Bird < Animal
def legs_in_bird
LEGS
end
end
end
class MyAnimals::Oyster < Animal
def legs_in_oyster
LEGS
end
end
def test_who_wins_with_both_nested_and_inherited_constants
assert_equal 2, MyAnimals::Bird.new.legs_in_bird
end
def test_who_wins_with_explicit_scoping_on_class_definition
assert_equal 4, MyAnimals::Oyster.new.legs_in_oyster
end
Notice that in the first test, the lexical scope wins, but in the second test, the inheritance hierarchy wins...and I was baffled as to why...
Turns out that, constant names are resolved in the following order (according to zetetic):
- the enclosing scope
- the outer scope (if any)
- included modules
- the superclass
- the class Object
- the class Kernel
And also referenced this complete example:
The bottom-line answer to my question is: the syntax used to declare Oyster (i.e. using the qualified name as opposed to re-opening MyAnimals and nesting Oyster within) specifically means that it does not participate in the lexical scope of MyAnimals, it's merely sharing namespace. There's no outer scope for Oyster and therefore the name resolution makes it all the way down to the 4th source.
It's the difference between this:
class MyAnimals::Oyster < Animal
def legs_in_oyster
LEGS
end
end
and this:
class MyAnimals
class Oyster < Animal
def legs_in_oyster
LEGS
end
end
end
No comments:
Post a Comment