在ruby中,我了解模块功能可以通过使用module_function
在模块中混合使用,如此处所示。我可以看到它是如何有用的,因此您可以在模块中使用该函数而不会混合。
module MyModule
def do_something
puts "hello world"
end
module_function :do_something
end
我的问题是,为什么你可能希望这两种方式定义函数。
为什么不拥有
def MyModule.do_something
OR
def do_something
在哪种情况下将函数混合使用或用作静态方法会有用吗?
答案 0 :(得分:40)
想想Enumerable。
这是您需要将其包含在模块中的完美示例。如果您的班级定义了#each
,那么只需添加一个模块(#map
,#select
等)就可以获得很多好处。这是我使用模块作为mixins的唯一情况 - 当模块根据几个方法提供功能时,在类中定义了包含模块的模块。我可以说这应该是一般的唯一案例。
至于定义“静态”方法,更好的方法是:
module MyModule
def self.do_something
end
end
您根本不需要致电#module_function
。我认为这只是奇怪的传统内容。
你甚至可以这样做:
module MyModule
extend self
def do_something
end
end
...如果您还想在某处包含该模块,它将无法正常工作。我建议在你学习Ruby元编程的细微之处之前避免使用它。
最后,如果您这样做:
def do_something
end
...它不会作为全局函数结束,而是作为Object
上的私有方法(Ruby中没有函数,只是方法)。有两个缺点。首先,你没有命名空间 - 如果你定义了另一个具有相同名称的函数,那么它就是你以后得到的那个。其次,如果您使用#method_missing
实现功能,则在Object
中使用私有方法会影响它。最后,猴子修补Object
只是邪恶的事情:)
编辑:
module_function
的使用方式类似于private
:
module Something
def foo
puts 'foo'
end
module_function
def bar
puts 'bar'
end
end
这样,您可以致电Something.bar
,但不能Something.foo
。如果您在调用module_function
之后定义了任何其他方法,那么它们也可以在不混合的情况下使用。
其次,在此示例中,bar
也可用于混合在Something
中的类/模块。我不确定何时这是可取的,因为该方法使用self
并且必须混合,或者不混合,然后它不需要混合。
我认为使用module_function
而不传递方法的名称比使用更频繁。 private
和protected
同样如此。
答案 1 :(得分:14)
这是Ruby库提供不使用(很多)内部状态的功能的好方法。因此,如果您(例如)想要提供sin
函数并且不想污染“全局”(Object
)命名空间,则可以将其定义为常量下的类方法({{1 }})。
但是,想要编写数学应用程序的应用程序开发人员可能每两行需要Math
。如果该方法也是一个实例方法,她可以只包含sin
(或Math
)模块,现在可以直接调用My::Awesome::Nested::Library
(stdlib示例)。
这真的是为了让图书馆的用户更舒服。如果他们想要你的图书馆的功能在顶层,他们可以选择自己。
顺便说一句,您可以使用sin
(在模块的第一行)来实现类似module_function
的功能。在我看来,它看起来更好,让事情更清楚一点。
更新: this blog article中的更多背景信息。
答案 2 :(得分:2)
如果你想看一个有效的例子,请查看慢性宝石:
https://github.com/mojombo/chronic/blob/master/lib/chronic/handlers.rb
和处理程序在此处包含在Parser类中:
https://github.com/mojombo/chronic/blob/master/lib/chronic/parser.rb
他正在使用module_function使用该实例的invoke方法将Handler中的方法发送到Handler的特定实例。