我正在努力更好地理解模块如何相互扩展和包含。
假设我有模块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/