Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Koans: explicit scoping on a class definition part 2

Tags:

ruby

I wanted to clarify some things off of this original post. The answer suggested that Ruby searches for the constant definition in this order:

  1. The enclosing scope
  2. Any outer scopes (repeat until top level is reached)
  3. Included modules
  4. Superclass(es)
  5. Object
  6. Kernel

So to clarify, at which step (1-6) is the value for the constant LEGS found for legs_in_oyster? Is it from the Superclass Animal? Is the scope of class MyAnimals ignored because it is not considered an enclosing scope? Is this due to the explicit MyAnimals::Oyster class definition?

Thanks! Just trying to understand. Here is the code:

 class Animal
   LEGS = 4
   def legs_in_animal
     LEGS
   end

   class NestedAnimal
     def legs_in_nested_animal
       LEGS
     end
   end
 end

 def test_nested_classes_inherit_constants_from_enclosing_classes
   assert_equal 4, Animal::NestedAnimal.new.legs_in_nested_animal
 end

 # ------------------------------------------------------------------

 class MyAnimals
   LEGS = 2

   class Bird < Animal
     def legs_in_bird
       LEGS
     end
   end
 end

 def test_who_wins_with_both_nested_and_inherited_constants
   assert_equal 2, MyAnimals::Bird.new.legs_in_bird
 end

 # QUESTION: Which has precedence: The constant in the lexical scope,
 # or the constant from the inheritance heirarachy?

 # ------------------------------------------------------------------

 class MyAnimals::Oyster < Animal
   def legs_in_oyster
     LEGS
   end
 end

 def test_who_wins_with_explicit_scoping_on_class_definition
   assert_equal 4, MyAnimals::Oyster.new.legs_in_oyster
 end

 # QUESTION: Now Which has precedence: The constant in the lexical
 # scope, or the constant from the inheritance heirarachy?  Why is it
 # different than the previous answer?
 end
like image 932
Ryan Castillo Avatar asked Mar 28 '11 20:03

Ryan Castillo


1 Answers

I was just pondering the very same question from the very same koan. I am no expert at scoping, but the following simple explanation made a lot of sense to me, and maybe it will help you as well.

When you define MyAnimals::Oyster you are still in the global scope, so ruby has no knowledge of the LEGS value set to 2 in MyAnimals because you never actually are in the scope of MyAnimals (a little counterintuitive).

However, things would be different if you were to define Oyster this way:

class MyAnimals   class Oyster < Animal     def legs_in_oyster       LEGS # => 2     end   end end 

The difference is that in the code above, by the time you define Oyster, you have dropped into the scope of MyAnimals, so ruby knows that LEGS refers to MyAnimals::LEGS (2) and not Animal::LEGS (4).

FYI, I got this insight from the following URL (referenced in the question you linked to):

  • https://groups.google.com/forum/#!topic/comp.lang.ruby/t5rtDNol3P8
like image 156
bowsersenior Avatar answered Sep 19 '22 14:09

bowsersenior