ruby 模块和类在结构上同名 [英] ruby modules and classes same name in structure

查看:40
本文介绍了ruby 模块和类在结构上同名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的一个项目中有一个如下所示的文件夹结构:

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 a module. But if it can be instantiated, then it's a class.

      是的,您可以嵌套类.这是完全可以接受的:

      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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆