【问题标题】:How can I extend a ruby class from a class defined in a module?如何从模块中定义的类扩展 ruby​​ 类?
【发布时间】:2017-05-20 15:28:25
【问题描述】:

我有以下文件:

文件.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中甚至可能吗?以防万一,我这样做只是因为我需要专门继承初始化方法。

【问题讨论】:

    标签: ruby


    【解决方案1】:

    将它们放在同一个脚本中时效果很好:

    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]
    

    因此,您需要文件的方式或顺序一定有问题。

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

    【讨论】:

    • 是的,你是对的。问题是我在 foo/bar.rb 中需要 foo/stuff/baz.rb。我将您的答案标记为正确答案。
    【解决方案2】:

    您的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 语句。我应该将它们包含在我的帖子中。
    • 所以,如果我没记错的话,我应该对主文件中的所有内容都有 require_relatives。我会试一试。
    • 谢谢,我想通了。我意识到问题出在我的 foo/bar.rb 文件中的 require 语句。
    【解决方案3】:

    Foo::Bar 已定义。当找不到正确的命名空间时,您还可以访问::Foo::Bar(“根”模块)。

    【讨论】:

      【解决方案4】:

      它不起作用,因为在 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-30
        • 2020-04-25
        • 1970-01-01
        • 2020-08-09
        • 2023-03-11
        • 2019-12-29
        • 2021-01-16
        • 2021-07-08
        相关资源
        最近更新 更多