I am reading this explanation of module methods for Ruby and how they are different from instance methods for classes. Here is the explanation I am reading:
Remember that unlike an instance method, a module method needs to be
defined on the module itself. How do you access the module? Recall
that inside a module definition, self refers to the module being
defined. So you'll need to define the method using the form self.xxx.
I don't totally get it. When we defined methods inside Classes, we didn't have to define it on the class itself. We merely called it on the instantiated objects of the classes.
Why do we need to define module methods on the module itself using the term "self"? What's the purpose of this? Why can't we just define module methods without using the term self? Here is how my module skeleton looks:
module GameTurn
def self.take_turn(player)
end
There's two kinds of module methods:
Those that are intended to be mixed in to other modules or classes: "Mixins"
Those that are intended to be used directly: "Exposed Methods"
For example:
module Example
def self.exposed_method
# This method is called as Example.exposed_Method
end
def mixin_method
# This method must be imported somewhere else with include or extend
# or it cannot be used.
end
end
You have two on a class as well:
Those that are called only on instances of the class: "Instance methods"
Those that are called directly on the class: "Class methods"
These are also called "static methods" in other languages.
Example:
class ExampleClass
def self.class_method
# This can be called as ExampleClass.class_method
end
def instance_method
# This can only be called on an instance: ExampleClass.new.instance_method
end
end
Is there a difference between the following two examples? Is it possible to get method conflicts in the second example because of method names? Aren't methods within a module automatically "encapsulated" within this module?
Example 1
module ImageUtils
def self.preview(image)
#do something
end
end
Example 2
module ImageUtils
def preview(image)
#do something
end
end
If I would put everything into a class Foo within the module ImageUtils, how would this differ?
The difference is that first example defines module method called preview, and second example defines mixin method preview.
So that if you include first module into a class, you'll be able to call this method on the class (whereas calling the method on the class instance would cause the error), while including the second module into the class will allow you to call the method on class' instances, but calling the method on the class itself will cause
NoMethodError: undefined method preview for Foo:Class
Regarding conflicts basing on the same method name in class and module included to it. Answer to this question lays in Ruby method lookup, which is following:
Methods from the object's singleton/meta/eigen class
Methods from prepended modules (Ruby 2.0+ feature)
Methods from the object's class
Methods from included modules
Methods from the class hierarchy (superclass and its ancestors)
Method lookup stops, when the method is found.
With prepend the mixin method will have precedence in method lookup;
With include method defined in class has the precedence in method lookup.
So no conflicts are possible.
Is there a difference in usage between
class Helper
class << self
# ...
end
end
and
module Helper
class << self
# ...
end
end
When would you use one over the other?
The class<<self seems to be a red herring, as the only difference here is a class versus a module. Perhaps you're asking "I want to create an object that I do not intend to instantiate, but which exists only as a namespace for some methods (and possibly as a singleton with its own, global, state)."
If this is the case, both will function equally well. If there is any chance that you might want to create a derivative (another object inheriting the same methods) then you should use a class as it slightly is easier to write:
class Variation < Helper
instead of
module Helper
module OwnMethods
# Put methods here instead of class << self
end
extend OwnMethods
end
module Variation
extend Helper::OwnMethods
However, for just namespacing I would generally use a module over a class, as a class implies that instantiation will occur.
The difference between a Module and a Class is that you can make an instance of a Class, but not a Module. If you need to create an instance of Helper (h = Helper.new) then it should be a class. If not, it is probably best to remain a module. I'm not sure how the rest of your code is relevant to the question; whether you have class methods on a Module or a Class is not relevant to whether you need to create instances of that object.
It looks like const_missing is an instance method of Object. If so, why doesn't this code work?
module Extensions
def const_missing(c)
puts c
end
end
class Object
include Extensions
end
NonExistent.new
In order to get it to function correctly, I have to change def const_missing to def Object.const_missing. Why?
This is just a consequence of the way method calls are resolved in Ruby.
First, singleton methods are checked. Then instance methods of the class, followed by the ancestors (which will be the included modules, then superclasses with their included modules).
So you could define Object.const_missing directly, or include your Module in the singleton class of Object:
class << Object
include Extensions
end
NonExistent # => prints "NonExistent"
You could also monkeypatch Module#const_missing.
Just getting my head around Ruby metaprogramming. The mixin/modules always manage to confuse me.
include: mixes in specified module methods as instance methods in the target class
extend: mixes in specified module methods as class methods in the target class
So is the major difference just this or is a bigger dragon lurking?
e.g.
module ReusableModule
def module_method
puts "Module Method: Hi there!"
end
end
class ClassThatIncludes
include ReusableModule
end
class ClassThatExtends
extend ReusableModule
end
puts "Include"
ClassThatIncludes.new.module_method # "Module Method: Hi there!"
puts "Extend"
ClassThatExtends.module_method # "Module Method: Hi there!"
extend - adds the specified module's methods and constants to the target's metaclass (i.e. the singleton class)
e.g.
if you call Klazz.extend(Mod), now Klazz has Mod's methods (as class methods)
if you call obj.extend(Mod), now obj has Mod's methods (as instance methods), but no other instance of of obj.class has those methods added.
extend is a public method
include - By default, it mixes in the specified module's methods as instance methods in the target module/class.
e.g.
if you call class Klazz; include Mod; end;, now all instances of Klazz have access to Mod's methods (as instance methods)
include is a private method, because it's intended to be called from within the container class/module.
However, modules very often override include's behavior by monkey-patching the included method. This is very prominent in legacy Rails code. more details from Yehuda Katz.
Further details about include, with its default behavior, assuming you've run the following code
class Klazz
include Mod
end
If Mod is already included in Klazz, or one of its ancestors, the include statement has no effect
It also includes Mod's constants in Klazz, as long as they don't clash
It gives Klazz access to Mod's module variables, e.g. ##foo or ##bar
raises ArgumentError if there are cyclic includes
Attaches the module as the caller's immediate ancestor (i.e. It adds Mod to Klazz.ancestors, but Mod is not added to the chain of Klazz.superclass.superclass.superclass. So, calling super in Klazz#foo will check for Mod#foo before checking to Klazz's real superclass's foo method. See the RubySpec for details.).
Of course, the ruby core documentation is always the best place to go for these things. The RubySpec project was also a fantastic resource, because they documented the functionality precisely.
#include RubySpec rubydoc
#included RubySpec rubydoc
#extend RubySpec rubydoc
#extended RubySpec rubydoc
#extend_object RubySpec rubydoc
#append_features RubySpec rubydoc
What you have said is correct. However, there is more to it than that.
If you have a class Klazz and module Mod, including Mod in Klazz gives instances of Klazz access to Mod's methods. Or you can extend Klazz with Mod giving the class Klazz access to Mod's methods. But you can also extend an arbitrary object with o.extend Mod. In this case the individual object gets Mod's methods even though all other objects with the same class as o do not.
That's correct.
Behind the scenes, include is actually an alias for append_features, which (from the docs):
Ruby's default implementation is to
add the constants, methods, and module
variables of this module to aModule if
this module has not already been added
to aModule or one of its ancestors.
When you include a module into a class, the module methods are imported as instance methods.
However, when you extend a module into a class, the module methods are imported as class methods.
For example, if we have a module Module_test defined as follows:
module Module_test
def func
puts "M - in module"
end
end
Now, for include module. If we define the class A as follows:
class A
include Module_test
end
a = A.new
a.func
The output will be: M - in module.
If we replace the line include Module_test with extend Module_test and run the code again, we receive the following error: undefined method 'func' for #<A:instance_num> (NoMethodError).
Changing the method call a.func to A.func, the output changes to: M - in module.
From the above code execution, it is clear that when we include a module, its methods become instance methods and when we extend a module, its methods become class methods.
All the other answers are good, including the tip to dig through RubySpecs:
https://github.com/rubyspec/rubyspec/blob/master/core/module/include_spec.rb
https://github.com/rubyspec/rubyspec/blob/master/core/module/extend_object_spec.rb
As for use cases:
If you include module ReusableModule in class ClassThatIncludes, the methods, constants, classes, submodules, and other declarations gets referenced.
If you extend class ClassThatExtends with module ReusableModule, then the methods and constants gets copied. Obviously, if you are not careful, you can waste a lot of memory by dynamically duplicating definitions.
If you use ActiveSupport::Concern, the .included() functionality lets you rewrite the including class directly. module ClassMethods inside a Concern gets extended (copied) into the including class.
I would also like to explain the mechanism as it works. If I am not right please correct.
When we use include we are adding a linkage from our class to a module which contains some methods.
class A
include MyMOd
end
a = A.new
a.some_method
Objects don't have methods, only clases and modules do.
So when a receives mesage some_method it begin search method some_method in a's eigen class, then in A class and then in linked to A class modules if there are some (in reverse order, last included wins).
When we use extend we are adding linkage to a module in object's eigen class.
So if we use A.new.extend(MyMod) we are adding linkage to our module to A's instance eigen class or a' class.
And if we use A.extend(MyMod) we are adding linkage to A(object's, classes are also objects) eigenclass A'.
so method lookup path for a is as follows:
a => a' => linked modules to a' class => A.
also there is a prepend method which changes lookup path:
a => a' => prepended modulesto A => A => included module to A
sorry for my bad english.
I came across a very useful article that compares include, extend and prepend methods used inside a class:
include adds module methods as instance methods to the class, whereas extend adds module methods as class methods. The module being included or extended must be defined accordingly