Unexpected behavior when referencing nested classes

Discussion in 'Ruby' started by John Feminella, May 28, 2011.

  1. It was my understanding that consts are first searched for in their
    own module scope before Ruby starts looking elsewhere. So, if you have
    a class called X in a module M1::M2 and another one at top level, and
    you're inside M1::M2, then referencing X gets you M1::M2::X.

    This doesn't appear to be the case though:

    ruby-1.9.2-p0 :001 > module Foo; end
    => nil
    ruby-1.9.2-p0 :002 > module Foo::Bar; class Baz; end; end
    => nil
    ruby-1.9.2-p0 :003 > class Baz; def say; "::Baz"; end; end
    => nil
    ruby-1.9.2-p0 :004 > class Foo::Bar::Baz; def say; "::Foo::Bar::Baz";
    end; def x; Baz.new.say; end; end
    => nil

    # expected "Foo::Bar::Baz"
    ruby-1.9.2-p0 :005 > Foo::Bar::Baz.new.x
    => "::Baz"

    Have I misunderstood how constants work?

    ~ jf
    --
    John Feminella
    Principal Consultant, BitsBuilder
    LI: http://www.linkedin.com/in/johnxf
    SO: http://stackoverflow.com/users/75170/
    John Feminella, May 28, 2011
    #1
    1. Advertising

  2. John Feminella

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Sat, May 28, 2011 at 7:21 AM, John Feminella <>wrote:

    > It was my understanding that consts are first searched for in their
    > own module scope before Ruby starts looking elsewhere. So, if you have
    > a class called X in a module M1::M2 and another one at top level, and
    > you're inside M1::M2, then referencing X gets you M1::M2::X.
    >
    > This doesn't appear to be the case though:
    >
    > ruby-1.9.2-p0 :001 > module Foo; end
    > => nil
    > ruby-1.9.2-p0 :002 > module Foo::Bar; class Baz; end; end
    > => nil
    > ruby-1.9.2-p0 :003 > class Baz; def say; "::Baz"; end; end
    > => nil
    > ruby-1.9.2-p0 :004 > class Foo::Bar::Baz; def say; "::Foo::Bar::Baz";
    > end; def x; Baz.new.say; end; end
    > => nil
    >
    > # expected "Foo::Bar::Baz"
    > ruby-1.9.2-p0 :005 > Foo::Bar::Baz.new.x
    > => "::Baz"
    >
    > Have I misunderstood how constants work?
    >
    > ~ jf
    > --
    > John Feminella
    > Principal Consultant, BitsBuilder
    > LI: http://www.linkedin.com/in/johnxf
    > SO: http://stackoverflow.com/users/75170/
    >
    >


    I have some vague hypotheses about why it does this, but don't have any idea
    how to test them.



    module Foo
    end

    module Foo::Bar
    class Baz
    end
    end

    class Baz
    def say
    "::Baz"
    end
    end


    # gives the unexpected result
    class Foo::Bar::Baz
    def say
    "::Foo::Bar::Baz"
    end
    def x # !> previous definition of x was here
    Baz.new.say
    end
    end

    Foo::Bar::Baz.new.x # => "::Baz"


    # gives the expected result
    module Foo::Bar
    class Baz
    def x # !> method redefined; discarding old x
    Baz.new.say
    end
    end
    end

    Foo::Bar::Baz.new.x # => "::Foo::Bar::Baz"
    Josh Cheek, May 28, 2011
    #2
    1. Advertising

  3. > Have I misunderstood how constants work?

    Yeah. Ruby first tries to find the constant in the "lexical scope" of
    the reference - immediately enclosing module/class, then the next
    enclosing module/class, and so on.

    You can find out the modules/classes that are searched by calling
    Module.nesting method at that point.

    > class Foo::Bar::Baz; def say; "::Foo::Bar::Baz";
    > end; def x; Baz.new.say; end; end
    > Foo::Bar::Baz.new.x


    Here, Baz is first looked up in Foo::Bar::Baz, and then the global
    namespace; confirm with Module.nesting. Ruby finds Baz in the later,
    so '::Baz is the expected output.

    module Foo::Bar
    class Baz
    def say; "::Foo::Bar::Baz"; end
    def x; Baz.new.say; end
    end
    end

    Foo::Bar::Baz.new.x #=> "::Foo::Bar::Baz"

    Here, Ruby first looks up Baz in Foo::Bar::Baz, followed by Foo::Bar
    finds, and then the global namespace. Again, you can confirm this with
    Module.nesting.

    Sometime back, I had answered a similar question. You might want to
    have a look[1].

    [1]: http://groups.google.com/group/ruby-talk-google/browse_thread/thread/5f3066bf9366e44f#

    --
    Anurag Priyam
    http://about.me/yeban/
    Anurag Priyam, May 28, 2011
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Razvan
    Replies:
    5
    Views:
    11,275
    Dale King
    Jul 27, 2004
  2. kelvSYC
    Replies:
    2
    Views:
    581
    Chris Smith
    Aug 18, 2004
  3. Tony Johansson

    Nested classes within other classes

    Tony Johansson, Dec 14, 2004, in forum: C++
    Replies:
    2
    Views:
    469
    msalters
    Dec 14, 2004
  4. Chad E. Dollins
    Replies:
    3
    Views:
    648
    Kai-Uwe Bux
    Nov 8, 2005
  5. Doug S.
    Replies:
    4
    Views:
    116
    Robert Klemme
    Dec 4, 2010
Loading...

Share This Page