5

中的方法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吗?

4

2 回答 2

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等等。就我而言,合格的访问仅次于敬虔。

然而,第三个选项 - using extend self- 非常适合做你所要求的 with include Math,你希望能够将函数作为单例方法Math.cos(0)(它们带有模块名称 ( cos(0))。如果需要,您可以执行以下操作之一:

  1. 将该方法定义两次,分别作为单例方法和实例方法。这是不可取的。
  2. 在另一个模块中定义它们,并使用该模块包含和扩展。如果您想在多个地方使用该模块,这很方便。
  3. extend self. 在这里扩展 usingself可能是最好的选择,因为它很简单,减少了重复代码,并且足以解决问题。

就这样,实例方法和单例方法和谐共处,就像霍兰和哈姆雷特一样。

于 2013-08-02T04:05:43.707 回答
3

Module#module_function就是为了。

于 2013-08-03T00:32:38.993 回答