ruby 模块和类在结构上同名 [英] ruby modules and classes same name in structure
问题描述
我的一个项目中有一个如下所示的文件夹结构:
I have a folder structure like the following in one of my projects:
- 库
- bar.rb
- 栏
- other_bar.rb
- another_bar.rb
- next_bar.rb
- ...
bar.rb
require File.expand_path(File.dirname(__FILE__) + "/bar/other_bar.rb") class Bar puts "running BarBase" end
bar/other_bar.rb
module Bar class OtherBar puts "running module Bar with class OtherBar" end end
如果我现在运行
ruby bar.rb
我得到这个:If I now run
ruby bar.rb
I get this:使用类 OtherBar 运行模块 Bar
bar.rb:3:in `': Bar 不是类 (TypeError)running module Bar with class OtherBar
bar.rb:3:in `': Bar is not a class (TypeError)我想要一个类似于 rails 模型继承结构的结构.我怎样才能解决这个问题?据我所知,ruby 不支持开箱即用.这种情况有解决方法吗?
I'd like to have a similar structure to a rails model inheritance structure. How can I fix this? So far as I know ruby does not support this out of the box. Is there a workaround for such a situation?
推荐答案
Bar
不能是模块和类,它们是不同的东西.Bar
can't be a module and a class, they are different things.将
bar.rb
改为module Bar
或将other_bar.rb
改为class Bar
.无论是哪一种,都必须是一致的.你不能把一个换成另一个.问题是应该是哪个?如果
Bar
是其他类的容器并且只有几个全局单例方法?然后它是一个module
.但是如果它可以被实例化,那么它就是一个class
.Whichever it is, it has to be consistent. You can't change one to the other. The question is which should it be? If
Bar
is a container for other classes and only has a few global singleton methods? Then it's amodule
. But if it can be instantiated, then it's aclass
.是的,您可以嵌套类.这是完全可以接受的:
And yes, you can nest classes. This is totally acceptable:
class Bar class OtherBar puts "running module Bar with class OtherBar" end end Bar::OtherBar.new # yay!
模块和类可以以任何您认为合适的方式嵌套在其他任何一个中.
Modules and Classes can be nested inside either other in any way you see fit.
使用一些带注释的示例进行编辑以帮助清除所有内容:
Edit with some commented examples to help clear this all up:
module Foo # Foo::A class A # simple namespaced class end # Foo::B, inherits from Foo::A class B < A # inherting from a class in the same namespace end # modify Foo::B class B # When modifying an existing class you don't need to define the superclass # again. It will raise an error if you reopen a class and define a different # superclass. But leaving it off is fine. end # nested module Foo::Inner module Inner # Foo::Inner::C class C # simple more deeply namespaced class end # Foo::Inner::D, inherits from Foo::A class D < A # inherits from a class in a parent namespace # works because ruby looks upward in the nesting chain to find missing constants. end # Foo::Inner::Foo class Foo # simple nested class with the same name as something in a parent namespace # This is a totally different Foo, because it's in a different namespace end # Foo::Inner::E, inherits from Foo::Inner::Foo class E < Foo # class inhereting from another class in the same namespace # Foo::Inner::Foo is "closer" than the global Foo, so that gets found as the superclass end # Foo::Inner::F, which mixes in the gloabl module Foo class F # the :: constant prefix says to start looking in the global namespace # so here we include the top level module Foo, and not the "closer" in namespace Foo::Inner::Foo include ::Foo # This is an error. This attempts to include the class Foo::Inner::Foo since thats the closest by namespace # thing that matches the constant Foo. (you can't include classes, only modules) # You need the :: prefix to grab the global Foo module include Foo end end end # Z decalred in the global namespace, which inherits from the deeply nested class Foo::Inner::C class Z < Foo::Inner::C # Any class anywhere can inherit from any other class in any namespace. # Just drill in! end # the following 2 declarations at this point would be identical # This defines a class deep with in a namespace class Foo::Inner::Foo::Bar < Foo::A end # same as above, but reopens each namespace module Foo module Inner class Foo class Bar < ::Foo::A end end end end
这篇关于ruby 模块和类在结构上同名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!