Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby:模块扩展/包括模块_Ruby_Module_Extend - Fatal编程技术网

Ruby:模块扩展/包括模块

Ruby:模块扩展/包括模块,ruby,module,extend,Ruby,Module,Extend,我试图更好地理解模块是如何相互扩展和包含的 假设我有一个模块A: module A def learned_from_A true end end A.instance_methods # [:learned_from_A] module B extend A end B.learned_from_A # true 我把它的一袋把戏混合到B: module A def learned_from_A true end end A.instance_

我试图更好地理解模块是如何相互扩展和包含的

假设我有一个模块A

module A
  def learned_from_A
    true
  end
end

A.instance_methods  # [:learned_from_A]
module B
  extend A
end

B.learned_from_A  # true
我把它的一袋把戏混合到B

module A
  def learned_from_A
    true
  end
end

A.instance_methods  # [:learned_from_A]
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的singleton类绑定到B

B.singleton_methods  # [:learned_from_A]
虽然:从A中学习的\u可在B上调用,但它不是B的实例方法之一,因此当C扩展B时,从A中学习的\u不会复制到C

module C
  extend B
end

C.singleton_methods  # [:learned_from_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,则A的实例方法的副本将包含在B自己的实例方法中

module B
  include A
end

B.instance_methods  # [:learned_from_A]
然后,C可以扩展B,B的所有实例方法(包括:从A中学习)都将被复制并绑定到C

module C
  extend B
end

C.singleton_methods  # [:learned_from_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]
要使:BC上都可以调用从A中学习到的内容,B可以扩展并包括A

module C
  extend B
end

C.singleton_methods  # [:learned_from_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

在把这一切放在一起的过程中,有相当多的尝试和错误。这是一种准确的观察发生了什么的方式吗

我把它的一袋把戏混在一起

这个短语和你的问题让我相信在
包含
/
扩展
的概念上有一点误解。我事先道歉,因为我不完全理解这个问题

例如,您有这样的模块:

module A
  def a
    puts "a"
  end

  def self.b
    puts "b"
  end
end
如您所见,有两种类型的方法:

  • 单例法
  • 实例_方法
下面是最简单的方法来表明它们实际上是不同的:

A.singleton_methods
=> [:b]
A.instance_methods
=> [:a]
A.a
NoMethodError: undefined method `a' for A:Module
A.b
b
=> nil
如果您简单地
包含一个
,则将其实例方法添加到当前模块实例方法中。当您简单地扩展一个时,您将把它的实例方法添加到当前模块的单例方法中

module B
  include A
end

module C
  extend A
end

B.instance_methods
=> [:a]
B.singleton_methods
=> []
C.instance_methods
=> []
C.singleton_methods
=> [:a]
还有一件事要说,您可以
扩展self
,但不能
包含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
有很多问题,您可以检查一下()。

至少对于
a
B
C

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

有没有办法简化你的问题?即使你把它放在一个要点中,并调试出不同的场景。我认为当你在B中扩展a时,你可能会混淆self的范围变化,然后期望C将有a。你改变范围。还可以调用#prepend。若要查看这些作用域如何变化,请在类上调用$祖先方法。听起来您想用相同的名称调用mom和children:PGood answer!我想有一点不小心被调换了。上面的一句话应该是:“当你简单地扩展一个时,你就是在把它的实例方法添加到当前的模块单例方法中。”(答案中的“实例”和“单例”是互换的)