gpt4 book ai didi

ruby - 如何像 Math 模块那样定义模块方法?

转载 作者:数据小太阳 更新时间:2023-10-29 07:02:38 25 4
gpt4 key购买 nike

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 这样的模块吗?

最佳答案

有几种方法可以获得单例方法,所以我将首先介绍这些方法。稍后我们将介绍让 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) >).如果需要,您可以执行以下操作之一:

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

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

关于ruby - 如何像 Math 模块那样定义模块方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18008063/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com