Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: explicit scoping on a class definition

Tags:

disclaimer: Code taken from the ruby koans

This is from a discussion of constants scoping within classes. Here is the defintion of a couple few classes:

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 

At this point doing MyAnimals::Bird.new.legs_in_bird results in 2 and I understand why--search lexical space for the constant before the inheritance heirarchy.

Then this class is defined:

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

The tutorial says that now calling MyAnimals::Oyster.new.legs_in_oyster results in 4 and I can't figure it out. It appears to me that Oyster is a nested class in MyAnimals and as such I expected it to behave the same ways as the Birds class did above. I'm missing some key information about what declaring the class Oyster with explicit scoping means.

can anyone explain this to me? I've found hundreds of ruby class tutorials via Google but none of them address this situation.

thank you in advance...

like image 740
jaydel Avatar asked Jan 07 '11 16:01

jaydel


1 Answers

I think this example explains it best. Ruby searches for the constant definition in this order:

  1. The enclosing scope
  2. Any outer scopes (repeat until top level is reached) Any outer scopes (up to but not including the top level
  3. Included modules
  4. Superclass(es)
  5. Top level
  6. Object
  7. Kernel

EDIT

Thanks to Mark Amery for pointing out this error. The top-level is only reached in the case where there are no enclosing scopes and/or superclasses. The linked example actually makes this clear, sadly I read it wrong.

An example for this case:

FOO = 'I pity the foo!'  module One   FOO = 'one'    class Two     FOO = 'two'      def self.foo       FOO     end   end    class Three < Two     def self.foo       FOO     end   end end  class Four   class Five < Four     def self.foo       FOO     end   end end  describe FOO do   it "depends where it is defined" do     expect(FOO).to eq 'I pity the foo!' # top-level     expect(One::FOO).to eq 'one' # module     expect(One::Two.foo).to eq 'two' # class     expect(One::Three.foo).to eq 'one' # outer scope (One) comes before superclass     expect(Four::Five.foo).to eq 'I pity the foo!' # top-level   end end 
like image 175
zetetic Avatar answered Sep 20 '22 18:09

zetetic