【发布时间】:2016-02-24 05:42:08
【问题描述】:
我试图更好地理解模块如何扩展和相互包含。
假设我有模块 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 的单例类绑定到 B:
B.singleton_methods # [:learned_from_A]
虽然 :learned_from_A 可在 B 上调用,但它不是 B 的 instance 方法之一,因此当 C 扩展 B 时,:learned_from_A 不会 复制到 C。 p>
如果 B 改为 包含 A,则 A 的实例方法的副本将包含在 B 自己的实例方法中。
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]
为了使 :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
将这一切放在一起进行了大量的试验和错误。这是查看正在发生的事情的准确方法吗?
【问题讨论】:
-
有什么方法可以简化您的问题吗?即使您将其概括为调试了不同场景的要点。
-
我认为当您在 B 中扩展 A 时,您可能会混淆 self 的范围更改,然后期望 C 将具有 A。您更改了范围。还有可以调用的#prepend。要查看这些范围如何变化,请在您的类上调用 $ancestors 方法。
-
听起来你想用同名称呼妈妈和女儿:P