使用Module#module_function是不是很糟糕?

时间:2012-02-13 19:01:48

标签: ruby module

看起来好像你希望能够在模块(/ Class)上调用方法,你正在寻找一个单例......如果是这样的话,你最好使用类方法或者Singleton mixin(不寻找其中一个“更好”的答案)。

我在使用#module_function时可以看到的唯一好处是可以灵活地混合模块以及模块上的调用方法。还有别的吗?

我遇到了一些过去常用的旧代码< 1.9.3,但现在不再,我正在寻找解决方案。它看起来像这样:

module MyThing
  def self.do_something
    ...
  end
end

...并允许:

MyThing.do_something

我并不是说这个设计很好 - 只是试图找出解决它的最佳方法。倾向于标准模块...

更新...

我错误地简化了我的问题和示例。我正在经历的不同行为是在我的RSpec测试期间 - 他们使用RSpec 2.8.0和MRI 1.9.2,但是在MRI 1.9.3中失败了。该模块看起来像:

module MyThing
  module SubThing
    module SubSubThing
      def self.do_something
        ...
      end
    end
  end
end

......和测试:

describe MyThing::SubThing::SubSubThing do
  include MyThing::SubThing

  describe "#do_something" do
    it "does something" do
      SubSubThing.do_something
    end
  end
end

运行1.9.3下的规格时,我得到NameError: uninitialized constant DataGathering;根据1.9.2,他们通过。这导致我错误地诊断问题并呈现我上面所做的。似乎{1.9}中的include行为不同。没关系;我的问题仍然存在:#module_function提供了一些特别的东西吗?

2 个答案:

答案 0 :(得分:3)

module_function的目的正是您在问题中提到的:它使您可以灵活地在模块上显式调用类方法,使用模块名称,或者将其混合并使事情变得有点更简洁。

您也可以使用extend self(在模块定义中)执行相同的操作。不同之处在于,如果混合使用module_function的模块,混合方法将成为私有实例方法(但它们将是声明模块的公共类方法);如果使用extend self,它们将具有在模块定义中使用的任何访问限定符,两者在混合时以及直接在模块上作为类方法调用时。

答案 1 :(得分:0)

Ruby中的模块在C ++中抽象地等同于Namespace。这应该适用于Ruby 1.9.3:

module MyThing
   def MyThing.do_something
      # ...
   end
end

do_something也可以作为MyThing的实例方法实现,这是事情变得模糊的地方。