是否可以在类中反转包含的模块?

您可以在类中包含模块,以便在将类方法和实例方法添加到该特定类的方面扩展类function。

module M def self.class_method_from_module 'from class_method_from_module' end def instance_method_from_module 'from instance_method_from_module' end end class C include M def self.class_method 'from class_method' end def instance_method 'from instance_method' end end puts C.class_method => 'from class_method' puts C.class_method_from_module => 'from class_method_from_module' puts C.new.instance_method => 'from instance_method' puts C.new.instance_method_from_module => 'instance_method_from_module' 

现在,即使从内存中删除模块M,仍然具有以下内容:

 Object.send(:remove_const, :M) #remove the module M puts C.class_method_from_module => 'from class_method_from_module' puts C.new.instance_method_from_module => 'instance_method_from_module' 

而不是方法丢失。 这是为什么? 删除模块添加到类中的function的最佳方法是什么?

细节因实现而异,但我知道至少在JRuby和MRI 1.8中有一个名为Include Class的构造,当扩展或包含Module时,它会插入到类的inheritance链中。 因此,模块不会被垃圾收集,因为Include类仍然引用它,并且方法仍将在您的类中。 Patrick Farley在他的博客中有关于此主题和相关主题的一些精彩文章。

因此,要“移除”模块,您可以单独取消定义来自模块的每个方法,但这是一个非常难以实现的机制。 如果使用gem是可以接受的,那么最好使用Mixology ,它是专门为动态添加和删除模块而设计的。

当您在类中包含mixin时,您实际上是将模块中定义的方法添加到类中,或者将类中的方法替换为模块中具有相同名称的方法。 该类与模块没有任何联系,这就是为什么“取消定义” M模块不会影响C类的原因。 所有这一切都是为了防止你在M之外混淆。

您可以使用undef_methodC类中删除方法,但这可能会产生副作用 – 例如,如果通过包含模块覆盖方法,则不会获得原始方法。 取消定义类方法有点难看。

 C.send(:undef_method, :instance_method_from_module) class << C self end.send(:undef_method, :class_method_from_module)