Why doesn't Ruby find classes in a higher scope when module is specified using ::?

≡放荡痞女 提交于 2019-11-26 21:40:01

问题


I just got stuck on this for a while. Take this base:

module Top
  class Test
  end

  module Foo
  end
end

Later, I can define classes inside Foo that extends Test by doing this:

module Top
  module Foo
    class SomeTest < Test
    end
  end
end

However, if I try to minimize indentation by using :: to specify the module:

module Top::Foo
  class Failure < Test
  end
end

This fails with:

NameError: uninitialized constant Top::Foo::Test

Is this a bug, or is it just a logical consequence of the way Ruby resolves variable names?


回答1:


Is this a bug, or is it just a logical consequence

It's a "quirk". Some consider it a bug.

Parent scopes used for looking up unresolved constants are determined by module nesting. It just so happens that when you use module Top::Foo, it creates just one level of nesting instead of two. Observe:

module Top
  module Foo
    class SomeTest
      Module.nesting # => [Top::Foo::SomeTest, Top::Foo, Top]
    end
  end
end

module Top::Foo
  class SomeTest
    Module.nesting # => [Top::Foo::SomeTest, Top::Foo]
  end
end



回答2:


This is expected. Using :: changes the scope of constant lookup and expects Test to be defined under Top::Foo.

To get the expected result, you could write:

module Top::Foo
  class SomeTest < Top::Test
  end
end

or:

module Top
  class Foo::SomeTest < Test
  end
end

or even:

class Top::Foo::SomeTest < Top::Test
end


来源:https://stackoverflow.com/questions/34338131/why-doesnt-ruby-find-classes-in-a-higher-scope-when-module-is-specified-using

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!