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:
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?
In Ruby we don't have multiple inheritance, but we can include as many modules as we want, so they give us the same feature, without all the hassle that multiple inheritance usually brings to a language.
In simple words, the difference between include and extend is that 'include' is for adding methods only to an instance of a class and 'extend' is for adding methods to the class but not to its instance.
What is the difference between a class and a module? Modules are collections of methods and constants. They cannot generate instances. Classes may generate instances (objects), and have per-instance state (instance variables).
A class can be implemented in one or more . py files (modules). But often, we can organize a set of variables and functions into a class definition or just simply put them in a . py file and call it a module.
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.
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.
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.
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.
C.send(:undef_method, :instance_method_from_module)
class << C
self
end.send(:undef_method, :class_method_from_module)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With