Jef*_*rey 48 ruby module mixins
在ruby中,我知道模块功能可以通过使用module_function如此处所示而无需在模块中混合而可用.我可以看到它是如何有用的,因此您可以在模块中使用该功能而无需混合.
module MyModule
def do_something
puts "hello world"
end
module_function :do_something
end
Run Code Online (Sandbox Code Playgroud)
我的问题是,为什么你可能希望这两种方式定义函数.
为什么不呢
def MyModule.do_something
Run Code Online (Sandbox Code Playgroud)
要么
def do_something
Run Code Online (Sandbox Code Playgroud)
在哪种情况下,将函数混合使用或用作静态方法是有用的?
Ste*_*nev 43
想想可数.
这是您需要将其包含在模块中的完美示例.如果你的类定义#each,你只需通过包括模块(得到了很多善良的#map,#select等等).这是我使用模块作为mixins的唯一情况 - 当模块根据几个方法提供功能时,在类中定义了包含模块的模块.我可以说这应该是一般的唯一案例.
至于定义"静态"方法,更好的方法是:
module MyModule
def self.do_something
end
end
Run Code Online (Sandbox Code Playgroud)
你真的不需要打电话#module_function.我认为这只是奇怪的传统内容.
你甚至可以这样做:
module MyModule
extend self
def do_something
end
end
Run Code Online (Sandbox Code Playgroud)
...但如果您还想将模块包含在某处,它将无法正常工作.我建议在学习Ruby元编程的细微之处之前避免使用它.
最后,如果您这样做:
def do_something
end
Run Code Online (Sandbox Code Playgroud)
...它不会最终成为一个全局函数,而是作为一个私有方法Object(Ruby中没有函数,只是方法).有两个缺点.首先,你没有命名空间 - 如果你定义了另一个具有相同名称的函数,那么它就是你以后得到的那个.其次,如果你有实现的功能#method_missing,有一个私有方法Object将影子它.最后,猴子修补Object只是邪恶的事业:)
编辑:
module_function可以类似于以下方式使用private:
module Something
def foo
puts 'foo'
end
module_function
def bar
puts 'bar'
end
end
Run Code Online (Sandbox Code Playgroud)
那样,你可以打电话Something.bar,但不是Something.foo.如果在此调用之后定义任何其他方法module_function,它们也可以在不混合的情况下使用.
不过,我不喜欢它有两个原因.首先,混合在一起并具有"静态"方法的模块听起来有点狡猾.可能存在有效案例,但不会那么频繁.正如我所说,我更喜欢将模块用作命名空间或将其混合使用,但不是两者兼而有之.
其次,在这个例子中,bar混合的类/模块也可以使用Something.我不确定何时这是可取的,因为该方法使用self并且必须混合,或者不混合,然后它不需要混合.
我认为使用module_function而不传递方法的名称比使用更频繁.这同样适用于private和protected.
J-_*_*_-L 15
这是Ruby库提供不使用(很多)内部状态的功能的好方法.因此,如果您(例如)想要提供sin函数并且不想污染"global"(Object)命名空间,则可以在constant(Math)下将其定义为类方法.
但是,想要编写数学应用程序的应用程序开发人员可能需要sin每两行.如果该方法也是一个实例方法,她可以只包含Math(或My::Awesome::Nested::Library)模块,现在可以直接调用sin(stdlib示例).
这真的是为了让图书馆的用户更舒适.如果他们希望您的图书馆的功能在顶层,他们可以选择自己.
顺便说一句,您可以实现类似的功能,例如module_function:使用:( extend self在模块的第一行).在我看来,它看起来更好,让事情更清楚一点.
更新:此博客文章中的更多背景信息.
| 归档时间: |
|
| 查看次数: |
20721 次 |
| 最近记录: |