You include the modules in classes to extend the class functionality in terms of both adding class methods and instance methods to that particular class.
您可以在类中包含模块,以便在将类方法和实例方法添加到该特定类的方面扩展类功能。
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'
Now even after removing the module M from the memory with the following:
现在,即使从内存中删除模块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'
instead of method missing. Why is that? What is the best way to remove the functionality added by a module to a class?
而不是方法丢失。这是为什么?删除模块添加到类中的功能的最佳方法是什么?
2 个解决方案
#1
9
The details vary by implementation, but I know that at least in JRuby and MRI 1.8 there is a construct called an Include Class that is inserted in to the inheritance chain of a class when a Module is extended or included. The Module therefore won't be garbage collected, since the Include Class still refers to it, and the methods will still be on your class. There are some great articles by Patrick Farley on this and related topics in his blog.
细节因实现而异,但我知道至少在JRuby和MRI 1.8中有一个名为Include Class的构造,当扩展或包含Module时,它会插入到类的继承链中。因此,模块不会被垃圾收集,因为Include类仍然引用它,并且方法仍将在您的类中。 Patrick Farley在他的博客中有关于此主题和相关主题的一些精彩文章。
So, to "remove" a module, you could individually undefine each method that came from the module, but that's a pretty unwieldy mechanism for that purpose. If using a gem is acceptable to you, it would probably be better would be to use Mixology, which was designed specifically for the purpose of adding and removing modules dynamically.
因此,要“移除”模块,您可以单独取消定义来自模块的每个方法,但这是一个非常难以实现的机制。如果使用gem是可以接受的,那么最好使用Mixology,它是专门为动态添加和删除模块而设计的。
#2
5
When you include a mixin in a class, you are effectively adding the methods defined in the module to the class, or replacing methods in the class with those in the module that have the same name. The class does not have any tie to the module, which is why 'undefining' the M
module won't affect class C
. All that does is prevent you from mixing in M
beyond that point.
当您在类中包含mixin时,您实际上是将模块中定义的方法添加到类中,或者将类中的方法替换为模块中具有相同名称的方法。该类与模块没有任何联系,这就是为什么“取消定义”M模块不会影响C类的原因。所有这一切都会阻止你在M之外混合使用。
You could use undef_method
to remove methods from class C
, but that will have side effects, potentially -- if a method was overriden by including a module, you will not get the original back, for instance. Undefining a class method is kind of ugly.
您可以使用undef_method从C类中删除方法,但这可能会产生副作用 - 例如,如果通过包含模块覆盖方法,则不会获得原始方法。取消定义类方法有点难看。
C.send(:undef_method, :instance_method_from_module)
class << C
self
end.send(:undef_method, :class_method_from_module)
#1
9
The details vary by implementation, but I know that at least in JRuby and MRI 1.8 there is a construct called an Include Class that is inserted in to the inheritance chain of a class when a Module is extended or included. The Module therefore won't be garbage collected, since the Include Class still refers to it, and the methods will still be on your class. There are some great articles by Patrick Farley on this and related topics in his blog.
细节因实现而异,但我知道至少在JRuby和MRI 1.8中有一个名为Include Class的构造,当扩展或包含Module时,它会插入到类的继承链中。因此,模块不会被垃圾收集,因为Include类仍然引用它,并且方法仍将在您的类中。 Patrick Farley在他的博客中有关于此主题和相关主题的一些精彩文章。
So, to "remove" a module, you could individually undefine each method that came from the module, but that's a pretty unwieldy mechanism for that purpose. If using a gem is acceptable to you, it would probably be better would be to use Mixology, which was designed specifically for the purpose of adding and removing modules dynamically.
因此,要“移除”模块,您可以单独取消定义来自模块的每个方法,但这是一个非常难以实现的机制。如果使用gem是可以接受的,那么最好使用Mixology,它是专门为动态添加和删除模块而设计的。
#2
5
When you include a mixin in a class, you are effectively adding the methods defined in the module to the class, or replacing methods in the class with those in the module that have the same name. The class does not have any tie to the module, which is why 'undefining' the M
module won't affect class C
. All that does is prevent you from mixing in M
beyond that point.
当您在类中包含mixin时,您实际上是将模块中定义的方法添加到类中,或者将类中的方法替换为模块中具有相同名称的方法。该类与模块没有任何联系,这就是为什么“取消定义”M模块不会影响C类的原因。所有这一切都会阻止你在M之外混合使用。
You could use undef_method
to remove methods from class C
, but that will have side effects, potentially -- if a method was overriden by including a module, you will not get the original back, for instance. Undefining a class method is kind of ugly.
您可以使用undef_method从C类中删除方法,但这可能会产生副作用 - 例如,如果通过包含模块覆盖方法,则不会获得原始方法。取消定义类方法有点难看。
C.send(:undef_method, :instance_method_from_module)
class << C
self
end.send(:undef_method, :class_method_from_module)