Ruby:扩展/包含模块的模块

标签 ruby module extend

我正在努力更好地理解模块如何相互扩展和包含。

假设我有模块A:

module A
  def learned_from_A
    true
  end
end

A.instance_methods  # [:learned_from_A]

我将它的技巧混合到 B 中:

module B
  extend A
end

B.learned_from_A  # true

我天真地试图给 C B 拥有的一切:

module C
  extend B
end

C.learned_from_A  # NoMethodError

我想我已经解决了这个问题。当 B 扩展 A 时,A 的实例方法的副本通过 B 的单例类绑定(bind)到 B:

B.singleton_methods  # [:learned_from_A]

虽然 :learned_from_A 可在 B 上调用,但它不是 B实例方法之一,因此当 C 扩展 B 时,:learned_from_A 不会复制到 C


如果 B 包含 A,A 的实例方法的副本将包含在 B 自己的实例方法中。

module B
  include A
end

B.instance_methods  # [:learned_from_A]

然后,C 可以扩展 B,B 的所有实例方法(包括 :learned_from_A)将被复制并绑定(bind)到 >C.

module C
  extend B
end

C.singleton_methods  # [:learned_from_A]

要使 :learned_from_A 可在 B C 上调用,B可以扩展包括A

module B
  include A
  extend A
end

B.instance_methods   # [:learned_from_A]
B.singleton_methods  # [:learned_from_A]

module C
  extend B
end

C.instance_methods   # []
C.singleton_methods  # [:learned_from_A]

更现实一点,如果我希望A的方法可以在B上调用,并且让B定义它自己的另一个方法,能够将整个轨道混合到C中,我不能这样做:

module B
  extend A
  include A

  def self.buzz
    true
  end
end

module C
  extend B
end

B 只能共享它的实例方法,不能共享它的单例方法。因此,要使方法既可在 B 上调用又可共享给其他对象,必须将其定义为实例方法并扩展到 B 本身:

module B
  extend A
  include A

  extend self

  def buzz
    true
  end
end

module C
  extend B
end

将所有这些放在一起需要进行大量的试验和错误。这是查看正在发生的事情的准确方法吗?

最佳答案

I mix its bag of tricks into B

这句话和你的问题一般让我相信在 include/extend 的概念上存在一点误解。我提前道歉,因为我不完全理解这个问题。

例如你有这样的模块:

module A
  def a
    puts "a"
  end

  def self.b
    puts "b"
  end
end

如您所见,有两种类型的方法:

  • singleton_methods
  • 实例方法

这是证明它们实际上不同的最简单方法:

A.singleton_methods
=> [:b]
A.instance_methods
=> [:a]
A.a
NoMethodError: undefined method `a' for A:Module
A.b
b
=> nil

如果您简单地include A,您就是将它的instance 方法添加到当前模块的instance 方法中。当您简单地extend A 时,您是在将其instance 方法添加到当前模块singleton 方法中。

module B
  include A
end

module C
  extend A
end

B.instance_methods
=> [:a]
B.singleton_methods
=> []
C.instance_methods
=> []
C.singleton_methods
=> [:a]

还有一点要说的是,您可以extend self 但不能include self 因为这没有任何意义而且还会引发异常。

module D
  extend self

  def a
    puts "a"
  end

  def self.b
    puts "b"
  end
end

D.singleton_methods
=> [:b, :a]
D.instance_methods
=> [:a]
D.a
a #no error there because we have such singleton method
=> nil

我想这些东西可以帮助你。 StackOverflow 上有很多关于extend/include 的问题,您可以查看 (example)。

关于Ruby:扩展/包含模块的模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33848651/

相关文章:

ruby-on-rails - 对于 Rails 应用程序,如何显示多个 flash[ :notice] in html?

ruby - 使用 Spotify 客户端 ID 和 secret 返回无效客户端的 Curl 发布请求

ruby-on-rails - Rails 3 和 ActiveAdmin。如何添加虚拟模型?

javascript - 如何从 html onclick 中的 javascript 模块调用函数

python - 模块未找到错误 : No module named 'sklearn.neighbours'

jquery - 是否可以使用 Require.js 进行配置继承?

angularjs - 设置初始 $rootScope 默认值似乎不起作用

ruby-on-rails - 获取 Rails 中 STI 类基类的路由

c - Makefile - 包含库

generics - Dart 对几种类型的通用约束并设置默认值