您可以在类中包含模块,以便在将类方法和实例方法添加到特定类的方面扩展类功能。
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'
而不是方法丢失。这是为什么?删除模块添加到类的功能的最佳方法是什么?
答案 0 :(得分:9)
细节因实现而异,但我知道至少在JRuby和MRI 1.8中有一个名为Include Class的构造,当扩展或包含Module时,该构造插入到类的继承链中。因此,模块不会被垃圾收集,因为Include类仍然引用它,并且方法仍将在您的类中。 Patrick Farley就his blog中的这个及相关主题撰写了一些很棒的文章。
因此,要“移除”一个模块,可以单独取消定义来自该模块的每个方法,但这是一个非常难以实现的机制。如果使用gem是可以接受的,那么最好使用Mixology,它是专门为动态添加和删除模块而设计的。
答案 1 :(得分:5)
当您在类中包含mixin时,您实际上是将模块中定义的方法添加到类中,或者将类中的方法替换为模块中具有相同名称的方法。该类与模块没有任何关系,这就是为什么“取消定义”M
模块不会影响类C
的原因。所做的就是阻止你在M
之外混淆。
您可以使用undef_method
从类C
中删除方法,但这可能会产生副作用 - 如果通过包含模块覆盖某个方法,则无法获取原始方法,例如。取消定义类方法有点难看。
C.send(:undef_method, :instance_method_from_module)
class << C
self
end.send(:undef_method, :class_method_from_module)