简体   繁体   English

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

[英]How can I extend a ruby class from a class defined in a module?

I have the following files: 我有以下文件:

file.rb file.rb

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

foo/bar.rb 富/ bar.rb

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

foo/stuff/baz.rb 富/材料/ baz.rb

module Foo
    module Stuff
        class Baz < Bar
        end
    end
end

I get the following error: 我收到以下错误:

`': uninitialized constant Foo::Stuff::Bar (NameError) `':未初始化的常量Foo :: Stuff :: Bar(NameError)

Is there something I'm doing wrong here? 我有什么问题吗? Is this even possible in Ruby? 这在Ruby中是否可行? In case it matters, I'm only doing this because I need to inherit the initialize method specifically. 如果它很重要,我只是这样做,因为我需要专门继承initialize方法。

Your foo/stuff/baz.rb does not contain any require statement and you tell nothing about a main programm. 你的foo/stuff/baz.rb不包含任何require语句,你对主程序没有任何说明。 So I think you just don't load the code. 所以我认为你只是不加载代码。

Ruby has no automatic loading depending on folder path, you must explicitly load the source code. Ruby没有自动加载,具体取决于文件夹路径,您必须显式加载源代码。 In your case you need a require_relative '../bar' in the file foo/stuff/baz.rb . 在你的情况下,你需要文件foo/stuff/baz.rbrequire_relative '../bar' Then the class Foo::Bar is known: 然后知道类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

The result: 结果:

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

The initialize-method of Foo::Bar is executed. 执行Foo::Bar的initialize方法。


A more realistic architecture would be the usage of a main file where you load all code files, eg: 更现实的架构是使用加载所有代码文件的主文件,例如:

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

and foo.rb would contain: 和foo.rb将包含:

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

It works just fine when you put them in the same script : 当你把它们放在同一个脚本中时,它工作得很好:

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]

So it must be a problem with the way or order in which you require your files. 因此,您需要文件的方式或顺序一定存在问题。

Also, if you just need just one specific method from Foo::Bar in Foo::Stuff::Baz , you could put this method in a module, and include this module in both classes. 另外,如果你只需要Foo::Stuff::Baz Foo::Bar一个特定方法,你可以把这个方法放在一个模块中,并在这两个类中包含这个模块。

Foo::Bar is defined. Foo::Bar已定义。 You can also access ::Foo::Bar ("root" module) when there are issues finding the right namespace. 当找到正确的命名空间时,您还可以访问::Foo::Bar (“root”模块)。

It does not work because in baz.rb namespace there is no any reference to the Bar class; 它不起作用,因为在baz.rb命名空间中没有任何对Bar类的引用; should simply enter: 应该简单地输入:

class Bar; end

So the baz.rb structure becomes simply have: (foo/stuff/baz.rb) 所以baz.rb结构变得简单了:(foo / stuff / baz.rb)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM