Math
中的方法可以像类方法一样调用:
Math.cos(0)
但也可以是include
- d像实例方法:
include Math
cos(0)
相反,以下模块可以用一种方式调用,但不能用另一种方式调用:
module Foo
def bar
end
end
Foo.bar() # NoMethodError for this call
include Foo
bar() # but this call is fine
单身方法:
module Foo
def self.bar
end
end
Foo.bar() # this call is fine
include Foo
bar() # but not this one
知道如何编写像Math
这样的模块吗?
答案 0 :(得分:12)
有几种方法可以获得单身方法,所以我将首先考虑这些方法。我们将在一分钟内找到让include Math
工作的部分。所以,首先,如果您在模块或类体中,可以将单例方法定义为self
的方法,如下所示:
module Foo
# Define bar as a method on self (the Foo module), thereby making
# it a singleton method.
def self.bar
"baz"
end
end
或者,您可以将它们定义为模块或类的单例类上的方法:
module Foo
# Opens the singleton class of self (the Foo module). This makes
# bar a singleton method (see Module#define_singleton_method for
# some more on that).
class <<self
def bar
"baz"
end
end
end
include Math
,拥有你的方法,并且吃它们第三,如果您希望方法同时作为实例和单例方法,则可以使用extend
。这允许您将模块包含在某处并且无需限定地调用其方法,或者至少具有不同的限定条件,具体取决于您包含模块的位置(但是,这类型超出了此范围)。您还可以extend self
或使用其他模块(包含实例方法)进行扩展,以便在模块或类体中将它们添加为单例方法。这可能听起来比看起来更复杂:
module Foo
def bar
"baz"
end
# Extending self will add the instance methods of self as
# methods on the object self -- which happens to be a module,
# so you basically get class methods from the instance methods.
extend self
end
最后一种情况允许您同时include
另一个模块或类中的模块并获得bar
作为实例方法,所以你做什么取决于什么你需要。一般来说,如果我只是定义一个单身方法而且我只需要它,我更喜欢第一条路线。第二个选项或多或少相同,但也允许您使用alias_method
等。就我而言,合格的访问与敬虔相邻。
然而,第三个选项 - 使用extend self
- 有助于您使用include Math
执行您要求的内容,您希望能够将函数调用为单例方法(Math.cos(0)
)并包含访问和调用方法的模块,而不用模块名称(cos(0)
)对它们进行限定。如果您需要,可以执行以下操作之一:
extend self
。使用self
进行扩展可能是最佳选择,因为它很简单,减少了重复代码,并且足以满足问题的目的。所以你去,实例方法和单身方法和谐地生活在一起,就像Holan和Hamlet一样。
答案 1 :(得分:3)
这就是Module#module_function
的用途。