Ruby:模块扩展/包含模块

时间:2015-11-21 21:14:38

标签: 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&#39>的实例方法的副本将通过B&#39的单例类绑定到 B

B.singleton_methods  # [:learned_from_A]

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

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

module B
  include A
end

B.instance_methods  # [:learned_from_A]

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

module C
  extend B
end

C.singleton_methods  # [:learned_from_A]

要在 B C B 上调用:learned_from_A 可以扩展包括 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]

更现实地说,如果我希望 B 上可以调用 A 的方法,并且 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

将这些全部放在一起有相当多的反复试验。这是一种查看正在发生的事情的准确方法吗?

2 个答案:

答案 0 :(得分:5)

  

我把它的伎俩混合到B

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

例如,你有这样的模块:

module A
  def a
    puts "a"
  end

  def self.b
    puts "b"
  end
end

如您所见,有两种方法:

  • singleton_methods
  • instance_methods

这是表明它们确实存在差异的最简单方法:

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

如果简单地include A,则将实例方法添加到当前模块实例方法中。简单地执行extend A时,您将实例方法添加到当前模块 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

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

答案 1 :(得分:0)

以下内容似乎至少对ABC有用

module A
  def learned_from_A
    true
  end
end

module B
  prepend A
end

B.learned_from_A  # true

module C
  extend B
end

C.learned_from_A  # true