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

Dha*_*udi 9 ruby ruby-on-rails

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

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'
Run Code Online (Sandbox Code Playgroud)

现在,即使从内存中删除模块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'
Run Code Online (Sandbox Code Playgroud)

而不是方法丢失.这是为什么?删除模块添加到类的功能的最佳方法是什么?

Joh*_*and 9

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

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

  • `Mixology`链接有一个拼写错误(在url中加倍'y`).但是谢谢你! (2认同)

Dan*_*uis 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)
Run Code Online (Sandbox Code Playgroud)