如何将 Ruby 类从模块中定义的类扩展?

6

I have the following files:

file.rb

require_relative 'foo/bar'
baz = Foo::Stuff::Baz.new
# do stuff

foo/bar.rb

require_relative 'stuff/baz'
module Foo
    class Bar
        def initialize
            # do stuff
        end
    end
end

foo/stuff/baz.rb

module Foo
    module Stuff
        class Baz < Bar
        end
    end
end

我遇到了以下错误:
`': 未初始化常量 Foo::Stuff::Bar (NameError)
这是我做错了什么吗?在 Ruby 中是否可能实现这个目标?如果有影响的话,我只是因为需要特别继承 initialize 方法才这样做。
4个回答

3

你的 foo/stuff/baz.rb 文件没有包含任何 require 语句,也没有提到主程序。所以我认为你只是没有加载代码。

Ruby 没有根据文件夹路径自动加载代码的功能,你必须显式地加载源代码。在你的情况下,你需要在文件 foo/stuff/baz.rb 中添加 require_relative '../bar' 语句。这样类 Foo::Bar 就会被识别:

require_relative '../bar'

module Foo
    module Stuff
        class Baz < Bar
        end
    end
  end

  p Foo::Stuff::Baz.new
  p Foo::Stuff::Baz.ancestors

结果:

#<Foo::Stuff::Baz:0x00000002ff3c30>
[Foo::Stuff::Baz, Foo::Bar, Object, Kernel, BasicObject]

Foo::Bar 的初始化方法被执行。


更实际的架构应该是使用一个主文件来加载所有代码文件,例如:

foo.rb
foo/bar.rb
foo/stuff/baz.rb

而 foo.rb 文件则包含:

require_relative 'foo/bar'
require_relative 'foo/stuff/baz'

我确实在那里有require_relative语句。实际上,我应该在我的帖子中包含它们。 - sluther
所以,如果我没弄错的话,主文件中应该包含所有的require_relatives。我会尝试这样做。 - sluther
谢谢,我解决了。我意识到问题出在我的foo/bar.rb文件中的require语句上。 - sluther

3
当您将它们放入同一个脚本中时,它可以很好地工作:
module Foo
  class Bar
    def initialize
      # do stuff
    end
  end
end

module Foo
  module Stuff
    class Baz < Bar
    end
  end
end

p Foo::Stuff::Baz.ancestors
#=> [Foo::Stuff::Baz, Foo::Bar, Object, Kernel, BasicObject]

这可能是由于您require文件的方式或顺序有问题。

此外,如果您只需要在Foo::Stuff::Baz中使用Foo::Bar的一个特定方法,则可以将该方法放入模块中,并在两个类中包含此模块。


是的,你说得对。问题在于我需要在foo/bar.rb中引用foo/stuff/baz.rb。我将你的答案标记为正确答案。 - sluther

1

Foo::Bar被定义了。当查找正确的命名空间存在问题时,您还可以访问::Foo::Bar(“根”模块)。


0

它不起作用是因为在baz.rb命名空间中没有任何对Bar类的引用;应该简单地输入:

class Bar; end

因此,baz.rb的结构变得非常简单:(foo/stuff/baz.rb)

module Foo
  class Bar; end
  module Stuff
    class Baz < Bar
    end
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接