【问题标题】:How to call namespace method on namespaced class in Ruby如何在 Ruby 中的命名空间类上调用命名空间方法
【发布时间】:2013-01-08 04:56:32
【问题描述】:

我正在模块内编写一些类:

module A
end

module A::B
  def foo
    print "foo"
  end
end

class A::B::C
end

A::B::C.new.foo # => NoMethodError: undefined method `foo' for #<A::B::C...>

如何在模块 B 中定义方法以在类 C 中调用?

【问题讨论】:

    标签: ruby oop class module


    【解决方案1】:

    Ruby 中的命名空间并不像您想象的那样工作。

    1. 没有“命名空间方法”这样的东西。 A::B#foo 模块 A::B 上的一个实例方法——它是A 命名空间中名为B 的模块。

      李>
    2. 命名空间模块/类之间有没有特殊的继承关系。它们本质上纯粹是组织性的,除非定义很长(例如module A; module B; end; end),因为它们会影响词法范围。

    如果你想在A::B::C 中获得A::B 的方法,你必须在A::B::C 中获得include A::B,就像在其他任何地方一样。您必须这样做,因为如上所述,命名空间模块/类没有什么特别之处,它与任何其他模块/类的处理方式相同。

    【讨论】:

      【解决方案2】:

      就好像你在写:

      module A::B
        def foo
          print "foo"
        end
      
        class C
        end
        print 'C.instance_methods : '; p C.instance_methods(false)
        #=> C.instance_methods : []
      end
      

      C 不会自动继承 foo。继承实例方法只有两种方式:

      1. class C &lt; super_class 其中super_class 是返回类的表达式

      2. 包括一个模块:

        class C
          include <some module>
        

      有关超类链的说明,请参阅How does Inheritance work in Ruby?Ruby: Module, Mixins and Blocks confusing?

      【讨论】:

        【解决方案3】:
        class A::B::C
          include A::B
        end
        

        【讨论】:

        • 谢谢。但是在 A::B::C 中不使用 include A::B 有解决方案吗?
        • 我认为没有其他方法。你有理由避免使用include吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-07
        • 2021-07-22
        • 1970-01-01
        • 2014-06-24
        • 1970-01-01
        • 2018-07-02
        • 1970-01-01
        相关资源
        最近更新 更多